Merge branch 'ionic-struct-cleanups'
Shannon Nelson says: ==================== ionic: struct cleanups This patchset has a few changes for better cacheline use, to cleanup a page handling API, and to streamline the Adminq/Notifyq queue handling. Lastly, we also have a couple of fixes pointed out by the friendly kernel test robot. v2: dropped change to irq coalesce default fixed Neel's attributions to Co-developed-by dropped the unnecessary new call to dma_sync_single_for_cpu() added 2 patches from kernel test robot results ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
22b330b622
|
@ -64,9 +64,6 @@ struct ionic_admin_ctx {
|
|||
union ionic_adminq_comp comp;
|
||||
};
|
||||
|
||||
int ionic_napi(struct napi_struct *napi, int budget, ionic_cq_cb cb,
|
||||
ionic_cq_done_cb done_cb, void *done_arg);
|
||||
|
||||
int ionic_adminq_post_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx);
|
||||
int ionic_dev_cmd_wait(struct ionic *ionic, unsigned long max_wait);
|
||||
int ionic_set_dma_mask(struct ionic *ionic);
|
||||
|
|
|
@ -467,9 +467,7 @@ int ionic_cq_init(struct ionic_lif *lif, struct ionic_cq *cq,
|
|||
struct ionic_intr_info *intr,
|
||||
unsigned int num_descs, size_t desc_size)
|
||||
{
|
||||
struct ionic_cq_info *cur;
|
||||
unsigned int ring_size;
|
||||
unsigned int i;
|
||||
|
||||
if (desc_size == 0 || !is_power_of_2(num_descs))
|
||||
return -EINVAL;
|
||||
|
@ -485,19 +483,6 @@ int ionic_cq_init(struct ionic_lif *lif, struct ionic_cq *cq,
|
|||
cq->tail_idx = 0;
|
||||
cq->done_color = 1;
|
||||
|
||||
cur = cq->info;
|
||||
|
||||
for (i = 0; i < num_descs; i++) {
|
||||
if (i + 1 == num_descs) {
|
||||
cur->next = cq->info;
|
||||
cur->last = true;
|
||||
} else {
|
||||
cur->next = cur + 1;
|
||||
}
|
||||
cur->index = i;
|
||||
cur++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -551,9 +536,7 @@ int ionic_q_init(struct ionic_lif *lif, struct ionic_dev *idev,
|
|||
unsigned int num_descs, size_t desc_size,
|
||||
size_t sg_desc_size, unsigned int pid)
|
||||
{
|
||||
struct ionic_desc_info *cur;
|
||||
unsigned int ring_size;
|
||||
unsigned int i;
|
||||
|
||||
if (desc_size == 0 || !is_power_of_2(num_descs))
|
||||
return -EINVAL;
|
||||
|
@ -574,18 +557,6 @@ int ionic_q_init(struct ionic_lif *lif, struct ionic_dev *idev,
|
|||
|
||||
snprintf(q->name, sizeof(q->name), "L%d-%s%u", lif->index, name, index);
|
||||
|
||||
cur = q->info;
|
||||
|
||||
for (i = 0; i < num_descs; i++) {
|
||||
if (i + 1 == num_descs)
|
||||
cur->next = q->info;
|
||||
else
|
||||
cur->next = cur + 1;
|
||||
cur->index = i;
|
||||
cur->left = num_descs - i;
|
||||
cur++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -652,6 +623,7 @@ void ionic_q_service(struct ionic_queue *q, struct ionic_cq_info *cq_info,
|
|||
struct ionic_desc_info *desc_info;
|
||||
ionic_desc_cb cb;
|
||||
void *cb_arg;
|
||||
u16 index;
|
||||
|
||||
/* check for empty queue */
|
||||
if (q->tail_idx == q->head_idx)
|
||||
|
@ -665,6 +637,7 @@ void ionic_q_service(struct ionic_queue *q, struct ionic_cq_info *cq_info,
|
|||
|
||||
do {
|
||||
desc_info = &q->info[q->tail_idx];
|
||||
index = q->tail_idx;
|
||||
q->tail_idx = (q->tail_idx + 1) & (q->num_descs - 1);
|
||||
|
||||
cb = desc_info->cb;
|
||||
|
@ -675,5 +648,5 @@ void ionic_q_service(struct ionic_queue *q, struct ionic_cq_info *cq_info,
|
|||
|
||||
if (cb)
|
||||
cb(q, desc_info, cq_info, cb_arg);
|
||||
} while (desc_info->index != stop_index);
|
||||
} while (index != stop_index);
|
||||
}
|
||||
|
|
|
@ -156,9 +156,6 @@ struct ionic_cq_info {
|
|||
struct ionic_admin_comp *admincq;
|
||||
struct ionic_notifyq_event *notifyq;
|
||||
};
|
||||
struct ionic_cq_info *next;
|
||||
unsigned int index;
|
||||
bool last;
|
||||
};
|
||||
|
||||
struct ionic_queue;
|
||||
|
@ -186,9 +183,6 @@ struct ionic_desc_info {
|
|||
struct ionic_txq_sg_desc *txq_sg_desc;
|
||||
struct ionic_rxq_sg_desc *rxq_sgl_desc;
|
||||
};
|
||||
struct ionic_desc_info *next;
|
||||
unsigned int index;
|
||||
unsigned int left;
|
||||
unsigned int npages;
|
||||
struct ionic_page_info pages[IONIC_RX_MAX_SG_ELEMS + 1];
|
||||
ionic_desc_cb cb;
|
||||
|
@ -199,16 +193,17 @@ struct ionic_desc_info {
|
|||
|
||||
struct ionic_queue {
|
||||
struct device *dev;
|
||||
u64 dbell_count;
|
||||
u64 drop;
|
||||
u64 stop;
|
||||
u64 wake;
|
||||
struct ionic_lif *lif;
|
||||
struct ionic_desc_info *info;
|
||||
struct ionic_dev *idev;
|
||||
u16 head_idx;
|
||||
u16 tail_idx;
|
||||
unsigned int index;
|
||||
unsigned int num_descs;
|
||||
u64 dbell_count;
|
||||
u64 stop;
|
||||
u64 wake;
|
||||
u64 drop;
|
||||
struct ionic_dev *idev;
|
||||
unsigned int type;
|
||||
unsigned int hw_index;
|
||||
unsigned int hw_type;
|
||||
|
@ -226,7 +221,6 @@ struct ionic_queue {
|
|||
};
|
||||
dma_addr_t base_pa;
|
||||
dma_addr_t sg_base_pa;
|
||||
unsigned int num_descs;
|
||||
unsigned int desc_size;
|
||||
unsigned int sg_desc_size;
|
||||
unsigned int pid;
|
||||
|
@ -246,8 +240,6 @@ struct ionic_intr_info {
|
|||
};
|
||||
|
||||
struct ionic_cq {
|
||||
void *base;
|
||||
dma_addr_t base_pa;
|
||||
struct ionic_lif *lif;
|
||||
struct ionic_cq_info *info;
|
||||
struct ionic_queue *bound_q;
|
||||
|
@ -255,8 +247,10 @@ struct ionic_cq {
|
|||
u16 tail_idx;
|
||||
bool done_color;
|
||||
unsigned int num_descs;
|
||||
u64 compl_count;
|
||||
unsigned int desc_size;
|
||||
u64 compl_count;
|
||||
void *base;
|
||||
dma_addr_t base_pa;
|
||||
};
|
||||
|
||||
struct ionic;
|
||||
|
|
|
@ -298,8 +298,8 @@ static void ionic_get_pauseparam(struct net_device *netdev,
|
|||
|
||||
pause_type = lif->ionic->idev.port_info->config.pause_type;
|
||||
if (pause_type) {
|
||||
pause->rx_pause = pause_type & IONIC_PAUSE_F_RX ? 1 : 0;
|
||||
pause->tx_pause = pause_type & IONIC_PAUSE_F_TX ? 1 : 0;
|
||||
pause->rx_pause = (pause_type & IONIC_PAUSE_F_RX) ? 1 : 0;
|
||||
pause->tx_pause = (pause_type & IONIC_PAUSE_F_TX) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -800,21 +800,6 @@ static bool ionic_notifyq_service(struct ionic_cq *cq,
|
|||
return true;
|
||||
}
|
||||
|
||||
static int ionic_notifyq_clean(struct ionic_lif *lif, int budget)
|
||||
{
|
||||
struct ionic_dev *idev = &lif->ionic->idev;
|
||||
struct ionic_cq *cq = &lif->notifyqcq->cq;
|
||||
u32 work_done;
|
||||
|
||||
work_done = ionic_cq_service(cq, budget, ionic_notifyq_service,
|
||||
NULL, NULL);
|
||||
if (work_done)
|
||||
ionic_intr_credits(idev->intr_ctrl, cq->bound_intr->index,
|
||||
work_done, IONIC_INTR_CRED_RESET_COALESCE);
|
||||
|
||||
return work_done;
|
||||
}
|
||||
|
||||
static bool ionic_adminq_service(struct ionic_cq *cq,
|
||||
struct ionic_cq_info *cq_info)
|
||||
{
|
||||
|
@ -830,15 +815,36 @@ static bool ionic_adminq_service(struct ionic_cq *cq,
|
|||
|
||||
static int ionic_adminq_napi(struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct ionic_intr_info *intr = napi_to_cq(napi)->bound_intr;
|
||||
struct ionic_lif *lif = napi_to_cq(napi)->lif;
|
||||
struct ionic_dev *idev = &lif->ionic->idev;
|
||||
unsigned int flags = 0;
|
||||
int n_work = 0;
|
||||
int a_work = 0;
|
||||
int work_done;
|
||||
|
||||
if (likely(lif->notifyqcq && lif->notifyqcq->flags & IONIC_QCQ_F_INITED))
|
||||
n_work = ionic_notifyq_clean(lif, budget);
|
||||
a_work = ionic_napi(napi, budget, ionic_adminq_service, NULL, NULL);
|
||||
if (lif->notifyqcq && lif->notifyqcq->flags & IONIC_QCQ_F_INITED)
|
||||
n_work = ionic_cq_service(&lif->notifyqcq->cq, budget,
|
||||
ionic_notifyq_service, NULL, NULL);
|
||||
|
||||
return max(n_work, a_work);
|
||||
if (lif->adminqcq && lif->adminqcq->flags & IONIC_QCQ_F_INITED)
|
||||
a_work = ionic_cq_service(&lif->adminqcq->cq, budget,
|
||||
ionic_adminq_service, NULL, NULL);
|
||||
|
||||
work_done = max(n_work, a_work);
|
||||
if (work_done < budget && napi_complete_done(napi, work_done)) {
|
||||
flags |= IONIC_INTR_CRED_UNMASK;
|
||||
DEBUG_STATS_INTR_REARM(intr);
|
||||
}
|
||||
|
||||
if (work_done || flags) {
|
||||
flags |= IONIC_INTR_CRED_RESET_COALESCE;
|
||||
ionic_intr_credits(idev->intr_ctrl,
|
||||
intr->index,
|
||||
n_work + a_work, flags);
|
||||
}
|
||||
|
||||
return work_done;
|
||||
}
|
||||
|
||||
void ionic_get_stats64(struct net_device *netdev,
|
||||
|
|
|
@ -16,32 +16,32 @@
|
|||
#define IONIC_TX_BUDGET_DEFAULT 256
|
||||
|
||||
struct ionic_tx_stats {
|
||||
u64 dma_map_err;
|
||||
u64 pkts;
|
||||
u64 bytes;
|
||||
u64 clean;
|
||||
u64 linearize;
|
||||
u64 csum_none;
|
||||
u64 csum;
|
||||
u64 crc32_csum;
|
||||
u64 tso;
|
||||
u64 tso_bytes;
|
||||
u64 frags;
|
||||
u64 vlan_inserted;
|
||||
u64 clean;
|
||||
u64 linearize;
|
||||
u64 crc32_csum;
|
||||
u64 sg_cntr[IONIC_MAX_NUM_SG_CNTR];
|
||||
u64 dma_map_err;
|
||||
};
|
||||
|
||||
struct ionic_rx_stats {
|
||||
u64 dma_map_err;
|
||||
u64 alloc_err;
|
||||
u64 pkts;
|
||||
u64 bytes;
|
||||
u64 csum_none;
|
||||
u64 csum_complete;
|
||||
u64 csum_error;
|
||||
u64 buffers_posted;
|
||||
u64 dropped;
|
||||
u64 vlan_stripped;
|
||||
u64 csum_error;
|
||||
u64 dma_map_err;
|
||||
u64 alloc_err;
|
||||
};
|
||||
|
||||
#define IONIC_QCQ_F_INITED BIT(0)
|
||||
|
|
|
@ -305,32 +305,6 @@ int ionic_adminq_post_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx)
|
|||
return ionic_adminq_check_err(lif, ctx, (remaining == 0));
|
||||
}
|
||||
|
||||
int ionic_napi(struct napi_struct *napi, int budget, ionic_cq_cb cb,
|
||||
ionic_cq_done_cb done_cb, void *done_arg)
|
||||
{
|
||||
struct ionic_qcq *qcq = napi_to_qcq(napi);
|
||||
struct ionic_cq *cq = &qcq->cq;
|
||||
u32 work_done, flags = 0;
|
||||
|
||||
work_done = ionic_cq_service(cq, budget, cb, done_cb, done_arg);
|
||||
|
||||
if (work_done < budget && napi_complete_done(napi, work_done)) {
|
||||
flags |= IONIC_INTR_CRED_UNMASK;
|
||||
DEBUG_STATS_INTR_REARM(cq->bound_intr);
|
||||
}
|
||||
|
||||
if (work_done || flags) {
|
||||
flags |= IONIC_INTR_CRED_RESET_COALESCE;
|
||||
ionic_intr_credits(cq->lif->ionic->idev.intr_ctrl,
|
||||
cq->bound_intr->index,
|
||||
work_done, flags);
|
||||
}
|
||||
|
||||
DEBUG_STATS_NAPI_POLL(qcq, work_done);
|
||||
|
||||
return work_done;
|
||||
}
|
||||
|
||||
static void ionic_dev_cmd_clean(struct ionic *ionic)
|
||||
{
|
||||
union ionic_dev_cmd_regs *regs = ionic->idev.dev_cmd_regs;
|
||||
|
|
|
@ -238,10 +238,10 @@ static bool ionic_rx_service(struct ionic_cq *cq, struct ionic_cq_info *cq_info)
|
|||
if (q->tail_idx == q->head_idx)
|
||||
return false;
|
||||
|
||||
desc_info = &q->info[q->tail_idx];
|
||||
if (desc_info->index != le16_to_cpu(comp->comp_index))
|
||||
if (q->tail_idx != le16_to_cpu(comp->comp_index))
|
||||
return false;
|
||||
|
||||
desc_info = &q->info[q->tail_idx];
|
||||
q->tail_idx = (q->tail_idx + 1) & (q->num_descs - 1);
|
||||
|
||||
/* clean the related q entry, only one per qc completion */
|
||||
|
@ -266,40 +266,49 @@ void ionic_rx_flush(struct ionic_cq *cq)
|
|||
work_done, IONIC_INTR_CRED_RESET_COALESCE);
|
||||
}
|
||||
|
||||
static struct page *ionic_rx_page_alloc(struct ionic_queue *q,
|
||||
dma_addr_t *dma_addr)
|
||||
static int ionic_rx_page_alloc(struct ionic_queue *q,
|
||||
struct ionic_page_info *page_info)
|
||||
{
|
||||
struct ionic_lif *lif = q->lif;
|
||||
struct ionic_rx_stats *stats;
|
||||
struct net_device *netdev;
|
||||
struct device *dev;
|
||||
struct page *page;
|
||||
|
||||
netdev = lif->netdev;
|
||||
dev = lif->ionic->dev;
|
||||
stats = q_to_rx_stats(q);
|
||||
page = alloc_page(GFP_ATOMIC);
|
||||
if (unlikely(!page)) {
|
||||
net_err_ratelimited("%s: Page alloc failed on %s!\n",
|
||||
|
||||
if (unlikely(!page_info)) {
|
||||
net_err_ratelimited("%s: %s invalid page_info in alloc\n",
|
||||
netdev->name, q->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
page_info->page = dev_alloc_page();
|
||||
if (unlikely(!page_info->page)) {
|
||||
net_err_ratelimited("%s: %s page alloc failed\n",
|
||||
netdev->name, q->name);
|
||||
stats->alloc_err++;
|
||||
return NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
*dma_addr = dma_map_page(dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE);
|
||||
if (unlikely(dma_mapping_error(dev, *dma_addr))) {
|
||||
__free_page(page);
|
||||
net_err_ratelimited("%s: DMA single map failed on %s!\n",
|
||||
page_info->dma_addr = dma_map_page(dev, page_info->page, 0, PAGE_SIZE,
|
||||
DMA_FROM_DEVICE);
|
||||
if (unlikely(dma_mapping_error(dev, page_info->dma_addr))) {
|
||||
put_page(page_info->page);
|
||||
page_info->dma_addr = 0;
|
||||
page_info->page = NULL;
|
||||
net_err_ratelimited("%s: %s dma map failed\n",
|
||||
netdev->name, q->name);
|
||||
stats->dma_map_err++;
|
||||
return NULL;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return page;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ionic_rx_page_free(struct ionic_queue *q, struct page *page,
|
||||
dma_addr_t dma_addr)
|
||||
static void ionic_rx_page_free(struct ionic_queue *q,
|
||||
struct ionic_page_info *page_info)
|
||||
{
|
||||
struct ionic_lif *lif = q->lif;
|
||||
struct net_device *netdev;
|
||||
|
@ -308,15 +317,23 @@ static void ionic_rx_page_free(struct ionic_queue *q, struct page *page,
|
|||
netdev = lif->netdev;
|
||||
dev = lif->ionic->dev;
|
||||
|
||||
if (unlikely(!page)) {
|
||||
net_err_ratelimited("%s: Trying to free unallocated buffer on %s!\n",
|
||||
if (unlikely(!page_info)) {
|
||||
net_err_ratelimited("%s: %s invalid page_info in free\n",
|
||||
netdev->name, q->name);
|
||||
return;
|
||||
}
|
||||
|
||||
dma_unmap_page(dev, dma_addr, PAGE_SIZE, DMA_FROM_DEVICE);
|
||||
if (unlikely(!page_info->page)) {
|
||||
net_err_ratelimited("%s: %s invalid page in free\n",
|
||||
netdev->name, q->name);
|
||||
return;
|
||||
}
|
||||
|
||||
__free_page(page);
|
||||
dma_unmap_page(dev, page_info->dma_addr, PAGE_SIZE, DMA_FROM_DEVICE);
|
||||
|
||||
put_page(page_info->page);
|
||||
page_info->dma_addr = 0;
|
||||
page_info->page = NULL;
|
||||
}
|
||||
|
||||
void ionic_rx_fill(struct ionic_queue *q)
|
||||
|
@ -352,8 +369,7 @@ void ionic_rx_fill(struct ionic_queue *q)
|
|||
desc->opcode = (nfrags > 1) ? IONIC_RXQ_DESC_OPCODE_SG :
|
||||
IONIC_RXQ_DESC_OPCODE_SIMPLE;
|
||||
desc_info->npages = nfrags;
|
||||
page_info->page = ionic_rx_page_alloc(q, &page_info->dma_addr);
|
||||
if (unlikely(!page_info->page)) {
|
||||
if (unlikely(ionic_rx_page_alloc(q, page_info))) {
|
||||
desc->addr = 0;
|
||||
desc->len = 0;
|
||||
return;
|
||||
|
@ -370,8 +386,7 @@ void ionic_rx_fill(struct ionic_queue *q)
|
|||
continue;
|
||||
|
||||
sg_elem = &sg_desc->elems[j];
|
||||
page_info->page = ionic_rx_page_alloc(q, &page_info->dma_addr);
|
||||
if (unlikely(!page_info->page)) {
|
||||
if (unlikely(ionic_rx_page_alloc(q, page_info))) {
|
||||
sg_elem->addr = 0;
|
||||
sg_elem->len = 0;
|
||||
return;
|
||||
|
@ -409,14 +424,8 @@ void ionic_rx_empty(struct ionic_queue *q)
|
|||
desc->addr = 0;
|
||||
desc->len = 0;
|
||||
|
||||
for (i = 0; i < desc_info->npages; i++) {
|
||||
if (likely(desc_info->pages[i].page)) {
|
||||
ionic_rx_page_free(q, desc_info->pages[i].page,
|
||||
desc_info->pages[i].dma_addr);
|
||||
desc_info->pages[i].page = NULL;
|
||||
desc_info->pages[i].dma_addr = 0;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < desc_info->npages; i++)
|
||||
ionic_rx_page_free(q, &desc_info->pages[i]);
|
||||
|
||||
desc_info->cb_arg = NULL;
|
||||
idx = (idx + 1) & (q->num_descs - 1);
|
||||
|
@ -626,6 +635,7 @@ static bool ionic_tx_service(struct ionic_cq *cq, struct ionic_cq_info *cq_info)
|
|||
struct ionic_txq_comp *comp = cq_info->cq_desc;
|
||||
struct ionic_queue *q = cq->bound_q;
|
||||
struct ionic_desc_info *desc_info;
|
||||
u16 index;
|
||||
|
||||
if (!color_match(comp->color, cq->done_color))
|
||||
return false;
|
||||
|
@ -635,11 +645,12 @@ static bool ionic_tx_service(struct ionic_cq *cq, struct ionic_cq_info *cq_info)
|
|||
*/
|
||||
do {
|
||||
desc_info = &q->info[q->tail_idx];
|
||||
index = q->tail_idx;
|
||||
q->tail_idx = (q->tail_idx + 1) & (q->num_descs - 1);
|
||||
ionic_tx_clean(q, desc_info, cq_info, desc_info->cb_arg);
|
||||
desc_info->cb = NULL;
|
||||
desc_info->cb_arg = NULL;
|
||||
} while (desc_info->index != le16_to_cpu(comp->comp_index));
|
||||
} while (index != le16_to_cpu(comp->comp_index));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -659,7 +670,6 @@ void ionic_tx_flush(struct ionic_cq *cq)
|
|||
void ionic_tx_empty(struct ionic_queue *q)
|
||||
{
|
||||
struct ionic_desc_info *desc_info;
|
||||
int done = 0;
|
||||
|
||||
/* walk the not completed tx entries, if any */
|
||||
while (q->head_idx != q->tail_idx) {
|
||||
|
@ -668,7 +678,6 @@ void ionic_tx_empty(struct ionic_queue *q)
|
|||
ionic_tx_clean(q, desc_info, NULL, desc_info->cb_arg);
|
||||
desc_info->cb = NULL;
|
||||
desc_info->cb_arg = NULL;
|
||||
done++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue