Commit 882f3b3b authored by Doug Ledford's avatar Doug Ledford

Merge branches '4.5/Or-cleanup' and '4.5/rdma-cq' into k.o/for-4.5

Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>

Conflicts:
	drivers/infiniband/ulp/iser/iser_verbs.c
parents 182a2da0 c6333f9f
...@@ -90,7 +90,7 @@ BLOCK_SOFTIRQ: Do all of the following: ...@@ -90,7 +90,7 @@ BLOCK_SOFTIRQ: Do all of the following:
from being initiated from tasks that might run on the CPU to from being initiated from tasks that might run on the CPU to
be de-jittered. (It is OK to force this CPU offline and then be de-jittered. (It is OK to force this CPU offline and then
bring it back online before you start your application.) bring it back online before you start your application.)
BLOCK_IOPOLL_SOFTIRQ: Do all of the following: IRQ_POLL_SOFTIRQ: Do all of the following:
1. Force block-device interrupts onto some other CPU. 1. Force block-device interrupts onto some other CPU.
2. Initiate any block I/O and block-I/O polling on other CPUs. 2. Initiate any block I/O and block-I/O polling on other CPUs.
3. Once your application has started, prevent CPU-hotplug operations 3. Once your application has started, prevent CPU-hotplug operations
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
obj-$(CONFIG_BLOCK) := bio.o elevator.o blk-core.o blk-tag.o blk-sysfs.o \ obj-$(CONFIG_BLOCK) := bio.o elevator.o blk-core.o blk-tag.o blk-sysfs.o \
blk-flush.o blk-settings.o blk-ioc.o blk-map.o \ blk-flush.o blk-settings.o blk-ioc.o blk-map.o \
blk-exec.o blk-merge.o blk-softirq.o blk-timeout.o \ blk-exec.o blk-merge.o blk-softirq.o blk-timeout.o \
blk-iopoll.o blk-lib.o blk-mq.o blk-mq-tag.o \ blk-lib.o blk-mq.o blk-mq-tag.o \
blk-mq-sysfs.o blk-mq-cpu.o blk-mq-cpumap.o ioctl.o \ blk-mq-sysfs.o blk-mq-cpu.o blk-mq-cpumap.o ioctl.o \
genhd.o scsi_ioctl.o partition-generic.o ioprio.o \ genhd.o scsi_ioctl.o partition-generic.o ioprio.o \
partitions/ partitions/
......
...@@ -5,6 +5,7 @@ menuconfig INFINIBAND ...@@ -5,6 +5,7 @@ menuconfig INFINIBAND
depends on NET depends on NET
depends on INET depends on INET
depends on m || IPV6 != m depends on m || IPV6 != m
select IRQ_POLL
---help--- ---help---
Core support for InfiniBand (IB). Make sure to also select Core support for InfiniBand (IB). Make sure to also select
any protocols you wish to use as well as drivers for your any protocols you wish to use as well as drivers for your
......
...@@ -8,7 +8,7 @@ obj-$(CONFIG_INFINIBAND_USER_MAD) += ib_umad.o ...@@ -8,7 +8,7 @@ obj-$(CONFIG_INFINIBAND_USER_MAD) += ib_umad.o
obj-$(CONFIG_INFINIBAND_USER_ACCESS) += ib_uverbs.o ib_ucm.o \ obj-$(CONFIG_INFINIBAND_USER_ACCESS) += ib_uverbs.o ib_ucm.o \
$(user_access-y) $(user_access-y)
ib_core-y := packer.o ud_header.o verbs.o sysfs.o \ ib_core-y := packer.o ud_header.o verbs.o cq.o sysfs.o \
device.o fmr_pool.o cache.o netlink.o \ device.o fmr_pool.o cache.o netlink.o \
roce_gid_mgmt.o roce_gid_mgmt.o
ib_core-$(CONFIG_INFINIBAND_USER_MEM) += umem.o ib_core-$(CONFIG_INFINIBAND_USER_MEM) += umem.o
......
/*
* Copyright (c) 2015 HGST, a Western Digital Company.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#include <linux/module.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <rdma/ib_verbs.h>
/* # of WCs to poll for with a single call to ib_poll_cq */
#define IB_POLL_BATCH 16
/* # of WCs to iterate over before yielding */
#define IB_POLL_BUDGET_IRQ 256
#define IB_POLL_BUDGET_WORKQUEUE 65536
#define IB_POLL_FLAGS \
(IB_CQ_NEXT_COMP | IB_CQ_REPORT_MISSED_EVENTS)
static int __ib_process_cq(struct ib_cq *cq, int budget)
{
int i, n, completed = 0;
while ((n = ib_poll_cq(cq, IB_POLL_BATCH, cq->wc)) > 0) {
for (i = 0; i < n; i++) {
struct ib_wc *wc = &cq->wc[i];
if (wc->wr_cqe)
wc->wr_cqe->done(cq, wc);
else
WARN_ON_ONCE(wc->status == IB_WC_SUCCESS);
}
completed += n;
if (n != IB_POLL_BATCH ||
(budget != -1 && completed >= budget))
break;
}
return completed;
}
/**
* ib_process_direct_cq - process a CQ in caller context
* @cq: CQ to process
* @budget: number of CQEs to poll for
*
* This function is used to process all outstanding CQ entries on a
* %IB_POLL_DIRECT CQ. It does not offload CQ processing to a different
* context and does not ask for completion interrupts from the HCA.
*
* Note: for compatibility reasons -1 can be passed in %budget for unlimited
* polling. Do not use this feature in new code, it will be removed soon.
*/
int ib_process_cq_direct(struct ib_cq *cq, int budget)
{
WARN_ON_ONCE(cq->poll_ctx != IB_POLL_DIRECT);
return __ib_process_cq(cq, budget);
}
EXPORT_SYMBOL(ib_process_cq_direct);
static void ib_cq_completion_direct(struct ib_cq *cq, void *private)
{
WARN_ONCE(1, "got unsolicited completion for CQ 0x%p\n", cq);
}
static int ib_poll_handler(struct irq_poll *iop, int budget)
{
struct ib_cq *cq = container_of(iop, struct ib_cq, iop);
int completed;
completed = __ib_process_cq(cq, budget);
if (completed < budget) {
irq_poll_complete(&cq->iop);
if (ib_req_notify_cq(cq, IB_POLL_FLAGS) > 0)
irq_poll_sched(&cq->iop);
}
return completed;
}
static void ib_cq_completion_softirq(struct ib_cq *cq, void *private)
{
irq_poll_sched(&cq->iop);
}
static void ib_cq_poll_work(struct work_struct *work)
{
struct ib_cq *cq = container_of(work, struct ib_cq, work);
int completed;
completed = __ib_process_cq(cq, IB_POLL_BUDGET_WORKQUEUE);
if (completed >= IB_POLL_BUDGET_WORKQUEUE ||
ib_req_notify_cq(cq, IB_POLL_FLAGS) > 0)
queue_work(ib_comp_wq, &cq->work);
}
static void ib_cq_completion_workqueue(struct ib_cq *cq, void *private)
{
queue_work(ib_comp_wq, &cq->work);
}
/**
* ib_alloc_cq - allocate a completion queue
* @dev: device to allocate the CQ for
* @private: driver private data, accessible from cq->cq_context
* @nr_cqe: number of CQEs to allocate
* @comp_vector: HCA completion vectors for this CQ
* @poll_ctx: context to poll the CQ from.
*
* This is the proper interface to allocate a CQ for in-kernel users. A
* CQ allocated with this interface will automatically be polled from the
* specified context. The ULP needs must use wr->wr_cqe instead of wr->wr_id
* to use this CQ abstraction.
*/
struct ib_cq *ib_alloc_cq(struct ib_device *dev, void *private,
int nr_cqe, int comp_vector, enum ib_poll_context poll_ctx)
{
struct ib_cq_init_attr cq_attr = {
.cqe = nr_cqe,
.comp_vector = comp_vector,
};
struct ib_cq *cq;
int ret = -ENOMEM;
cq = dev->create_cq(dev, &cq_attr, NULL, NULL);
if (IS_ERR(cq))
return cq;
cq->device = dev;
cq->uobject = NULL;
cq->event_handler = NULL;
cq->cq_context = private;
cq->poll_ctx = poll_ctx;
atomic_set(&cq->usecnt, 0);
cq->wc = kmalloc_array(IB_POLL_BATCH, sizeof(*cq->wc), GFP_KERNEL);
if (!cq->wc)
goto out_destroy_cq;
switch (cq->poll_ctx) {
case IB_POLL_DIRECT:
cq->comp_handler = ib_cq_completion_direct;
break;
case IB_POLL_SOFTIRQ:
cq->comp_handler = ib_cq_completion_softirq;
irq_poll_init(&cq->iop, IB_POLL_BUDGET_IRQ, ib_poll_handler);
ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
break;
case IB_POLL_WORKQUEUE:
cq->comp_handler = ib_cq_completion_workqueue;
INIT_WORK(&cq->work, ib_cq_poll_work);
ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
break;
default:
ret = -EINVAL;
goto out_free_wc;
}
return cq;
out_free_wc:
kfree(cq->wc);
out_destroy_cq:
cq->device->destroy_cq(cq);
return ERR_PTR(ret);
}
EXPORT_SYMBOL(ib_alloc_cq);
/**
* ib_free_cq - free a completion queue
* @cq: completion queue to free.
*/
void ib_free_cq(struct ib_cq *cq)
{
int ret;
if (WARN_ON_ONCE(atomic_read(&cq->usecnt)))
return;
switch (cq->poll_ctx) {
case IB_POLL_DIRECT:
break;
case IB_POLL_SOFTIRQ:
irq_poll_disable(&cq->iop);
break;
case IB_POLL_WORKQUEUE:
flush_work(&cq->work);
break;
default:
WARN_ON_ONCE(1);
}
kfree(cq->wc);
ret = cq->device->destroy_cq(cq);
WARN_ON_ONCE(ret);
}
EXPORT_SYMBOL(ib_free_cq);
...@@ -58,6 +58,7 @@ struct ib_client_data { ...@@ -58,6 +58,7 @@ struct ib_client_data {
bool going_down; bool going_down;
}; };
struct workqueue_struct *ib_comp_wq;
struct workqueue_struct *ib_wq; struct workqueue_struct *ib_wq;
EXPORT_SYMBOL_GPL(ib_wq); EXPORT_SYMBOL_GPL(ib_wq);
...@@ -943,10 +944,18 @@ static int __init ib_core_init(void) ...@@ -943,10 +944,18 @@ static int __init ib_core_init(void)
if (!ib_wq) if (!ib_wq)
return -ENOMEM; return -ENOMEM;
ib_comp_wq = alloc_workqueue("ib-comp-wq",
WQ_UNBOUND | WQ_HIGHPRI | WQ_MEM_RECLAIM,
WQ_UNBOUND_MAX_ACTIVE);
if (!ib_comp_wq) {
ret = -ENOMEM;
goto err;
}
ret = class_register(&ib_class); ret = class_register(&ib_class);
if (ret) { if (ret) {
printk(KERN_WARNING "Couldn't create InfiniBand device class\n"); printk(KERN_WARNING "Couldn't create InfiniBand device class\n");
goto err; goto err_comp;
} }
ret = ibnl_init(); ret = ibnl_init();
...@@ -961,7 +970,8 @@ static int __init ib_core_init(void) ...@@ -961,7 +970,8 @@ static int __init ib_core_init(void)
err_sysfs: err_sysfs:
class_unregister(&ib_class); class_unregister(&ib_class);
err_comp:
destroy_workqueue(ib_comp_wq);
err: err:
destroy_workqueue(ib_wq); destroy_workqueue(ib_wq);
return ret; return ret;
...@@ -972,6 +982,7 @@ static void __exit ib_core_cleanup(void) ...@@ -972,6 +982,7 @@ static void __exit ib_core_cleanup(void)
ib_cache_cleanup(); ib_cache_cleanup();
ibnl_cleanup(); ibnl_cleanup();
class_unregister(&ib_class); class_unregister(&ib_class);
destroy_workqueue(ib_comp_wq);
/* Make sure that any pending umem accounting work is done. */ /* Make sure that any pending umem accounting work is done. */
destroy_workqueue(ib_wq); destroy_workqueue(ib_wq);
} }
......
...@@ -70,7 +70,6 @@ static struct ib_qp_attr ipoib_cm_err_attr = { ...@@ -70,7 +70,6 @@ static struct ib_qp_attr ipoib_cm_err_attr = {
#define IPOIB_CM_RX_DRAIN_WRID 0xffffffff #define IPOIB_CM_RX_DRAIN_WRID 0xffffffff
static struct ib_send_wr ipoib_cm_rx_drain_wr = { static struct ib_send_wr ipoib_cm_rx_drain_wr = {
.wr_id = IPOIB_CM_RX_DRAIN_WRID,
.opcode = IB_WR_SEND, .opcode = IB_WR_SEND,
}; };
...@@ -223,6 +222,7 @@ static void ipoib_cm_start_rx_drain(struct ipoib_dev_priv *priv) ...@@ -223,6 +222,7 @@ static void ipoib_cm_start_rx_drain(struct ipoib_dev_priv *priv)
* error" WC will be immediately generated for each WR we post. * error" WC will be immediately generated for each WR we post.
*/ */
p = list_entry(priv->cm.rx_flush_list.next, typeof(*p), list); p = list_entry(priv->cm.rx_flush_list.next, typeof(*p), list);
ipoib_cm_rx_drain_wr.wr_id = IPOIB_CM_RX_DRAIN_WRID;
if (ib_post_send(p->qp, &ipoib_cm_rx_drain_wr, &bad_wr)) if (ib_post_send(p->qp, &ipoib_cm_rx_drain_wr, &bad_wr))
ipoib_warn(priv, "failed to post drain wr\n"); ipoib_warn(priv, "failed to post drain wr\n");
......
...@@ -151,16 +151,12 @@ ...@@ -151,16 +151,12 @@
- ISER_MAX_RX_MISC_PDUS) / \ - ISER_MAX_RX_MISC_PDUS) / \
(1 + ISER_INFLIGHT_DATAOUTS)) (1 + ISER_INFLIGHT_DATAOUTS))
#define ISER_WC_BATCH_COUNT 16
#define ISER_SIGNAL_CMD_COUNT 32 #define ISER_SIGNAL_CMD_COUNT 32
#define ISER_VER 0x10 #define ISER_VER 0x10
#define ISER_WSV 0x08 #define ISER_WSV 0x08
#define ISER_RSV 0x04 #define ISER_RSV 0x04
#define ISER_FASTREG_LI_WRID 0xffffffffffffffffULL
#define ISER_BEACON_WRID 0xfffffffffffffffeULL
/** /**
* struct iser_hdr - iSER header * struct iser_hdr - iSER header
* *
...@@ -269,7 +265,7 @@ enum iser_desc_type { ...@@ -269,7 +265,7 @@ enum iser_desc_type {
#define ISER_MAX_WRS 7 #define ISER_MAX_WRS 7
/** /**
* struct iser_tx_desc - iSER TX descriptor (for send wr_id) * struct iser_tx_desc - iSER TX descriptor
* *
* @iser_header: iser header * @iser_header: iser header
* @iscsi_header: iscsi header * @iscsi_header: iscsi header
...@@ -293,6 +289,7 @@ struct iser_tx_desc { ...@@ -293,6 +289,7 @@ struct iser_tx_desc {
u64 dma_addr; u64 dma_addr;
struct ib_sge tx_sg[2]; struct ib_sge tx_sg[2];
int num_sge; int num_sge;
struct ib_cqe cqe;
bool mapped; bool mapped;
u8 wr_idx; u8 wr_idx;
union iser_wr { union iser_wr {
...@@ -306,9 +303,10 @@ struct iser_tx_desc { ...@@ -306,9 +303,10 @@ struct iser_tx_desc {
}; };
#define ISER_RX_PAD_SIZE (256 - (ISER_RX_PAYLOAD_SIZE + \ #define ISER_RX_PAD_SIZE (256 - (ISER_RX_PAYLOAD_SIZE + \
sizeof(u64) + sizeof(struct ib_sge))) sizeof(u64) + sizeof(struct ib_sge) + \
sizeof(struct ib_cqe)))
/** /**
* struct iser_rx_desc - iSER RX descriptor (for recv wr_id) * struct iser_rx_desc - iSER RX descriptor
* *
* @iser_header: iser header * @iser_header: iser header
* @iscsi_header: iscsi header * @iscsi_header: iscsi header
...@@ -323,7 +321,27 @@ struct iser_rx_desc { ...@@ -323,7 +321,27 @@ struct iser_rx_desc {
char data[ISER_RECV_DATA_SEG_LEN]; char data[ISER_RECV_DATA_SEG_LEN];
u64 dma_addr; u64 dma_addr;
struct ib_sge rx_sg; struct ib_sge rx_sg;
struct ib_cqe cqe;
char pad[ISER_RX_PAD_SIZE]; char pad[ISER_RX_PAD_SIZE];
} __packed;
/**
* struct iser_login_desc - iSER login descriptor
*
* @req: pointer to login request buffer
* @resp: pointer to login response buffer
* @req_dma: DMA address of login request buffer
* @rsp_dma: DMA address of login response buffer
* @sge: IB sge for login post recv
* @cqe: completion handler
*/
struct iser_login_desc {
void *req;
void *rsp;
u64 req_dma;
u64 rsp_dma;
struct ib_sge sge;
struct ib_cqe cqe;
} __attribute__((packed)); } __attribute__((packed));
struct iser_conn; struct iser_conn;
...@@ -333,18 +351,12 @@ struct iscsi_iser_task; ...@@ -333,18 +351,12 @@ struct iscsi_iser_task;
/** /**
* struct iser_comp - iSER completion context * struct iser_comp - iSER completion context
* *
* @device: pointer to device handle
* @cq: completion queue * @cq: completion queue
* @wcs: work completion array
* @tasklet: Tasklet handle
* @active_qps: Number of active QPs attached * @active_qps: Number of active QPs attached
* to completion context * to completion context
*/ */
struct iser_comp { struct iser_comp {
struct iser_device *device;
struct ib_cq *cq; struct ib_cq *cq;
struct ib_wc wcs[ISER_WC_BATCH_COUNT];
struct tasklet_struct tasklet;
int active_qps; int active_qps;
}; };
...@@ -473,10 +485,11 @@ struct iser_fr_pool { ...@@ -473,10 +485,11 @@ struct iser_fr_pool {
* @rx_wr: receive work request for batch posts * @rx_wr: receive work request for batch posts
* @device: reference to iser device * @device: reference to iser device
* @comp: iser completion context * @comp: iser completion context
* @pi_support: Indicate device T10-PI support
* @beacon: beacon send wr to signal all flush errors were drained
* @flush_comp: completes when all connection completions consumed
* @fr_pool: connection fast registration poool * @fr_pool: connection fast registration poool
* @pi_support: Indicate device T10-PI support
* @last: last send wr to signal all flush errors were drained
* @last_cqe: cqe handler for last wr
* @last_comp: completes when all connection completions consumed
*/ */
struct ib_conn { struct ib_conn {
struct rdma_cm_id *cma_id; struct rdma_cm_id *cma_id;
...@@ -486,10 +499,12 @@ struct ib_conn { ...@@ -486,10 +499,12 @@ struct ib_conn {
struct ib_recv_wr rx_wr[ISER_MIN_POSTED_RX]; struct ib_recv_wr rx_wr[ISER_MIN_POSTED_RX];
struct iser_device *device; struct iser_device *device;
struct iser_comp *comp; struct iser_comp *comp;
bool pi_support;
struct ib_send_wr beacon;
struct completion flush_comp;
struct iser_fr_pool fr_pool; struct iser_fr_pool fr_pool;
bool pi_support;
struct ib_send_wr last;
struct ib_cqe last_cqe;
struct ib_cqe reg_cqe;
struct completion last_comp;
}; };
/** /**
...@@ -512,11 +527,7 @@ struct ib_conn { ...@@ -512,11 +527,7 @@ struct ib_conn {
* @up_completion: connection establishment completed * @up_completion: connection establishment completed
* (state is ISER_CONN_UP) * (state is ISER_CONN_UP)
* @conn_list: entry in ig conn list * @conn_list: entry in ig conn list
* @login_buf: login data buffer (stores login parameters) * @login_desc: login descriptor
* @login_req_buf: login request buffer
* @login_req_dma: login request buffer dma address
* @login_resp_buf: login response buffer
* @login_resp_dma: login response buffer dma address
* @rx_desc_head: head of rx_descs cyclic buffer * @rx_desc_head: head of rx_descs cyclic buffer
* @rx_descs: rx buffers array (cyclic buffer) * @rx_descs: rx buffers array (cyclic buffer)
* @num_rx_descs: number of rx descriptors * @num_rx_descs: number of rx descriptors
...@@ -539,10 +550,7 @@ struct iser_conn { ...@@ -539,10 +550,7 @@ struct iser_conn {
struct completion ib_completion; struct completion ib_completion;
struct completion up_completion; struct completion up_completion;
struct list_head conn_list; struct list_head conn_list;
struct iser_login_desc login_desc;
char *login_buf;
char *login_req_buf, *login_resp_buf;
u64 login_req_dma, login_resp_dma;
unsigned int rx_desc_head; unsigned int rx_desc_head;
struct iser_rx_desc *rx_descs; struct iser_rx_desc *rx_descs;
u32 num_rx_descs; u32 num_rx_descs;
...@@ -631,12 +639,14 @@ int iser_conn_terminate(struct iser_conn *iser_conn); ...@@ -631,12 +639,14 @@ int iser_conn_terminate(struct iser_conn *iser_conn);
void iser_release_work(struct work_struct *work); void iser_release_work(struct work_struct *work);
void iser_rcv_completion(struct iser_rx_desc *desc, void iser_err_comp(struct ib_wc *wc, const char *type);
unsigned long dto_xfer_len, void iser_login_rsp(struct ib_cq *cq, struct ib_wc *wc);
struct ib_conn *ib_conn); void iser_task_rsp(struct ib_cq *cq, struct ib_wc *wc);
void iser_cmd_comp(struct ib_cq *cq, struct ib_wc *wc);
void iser_snd_completion(struct iser_tx_desc *desc, void iser_ctrl_comp(struct ib_cq *cq, struct ib_wc *wc);
struct ib_conn *ib_conn); void iser_dataout_comp(struct ib_cq *cq, struct ib_wc *wc);
void iser_reg_comp(struct ib_cq *cq, struct ib_wc *wc);
void iser_last_comp(struct ib_cq *cq, struct ib_wc *wc);
void iser_task_rdma_init(struct iscsi_iser_task *task); void iser_task_rdma_init(struct iscsi_iser_task *task);
...@@ -717,4 +727,28 @@ iser_tx_next_wr(struct iser_tx_desc *tx_desc) ...@@ -717,4 +727,28 @@ iser_tx_next_wr(struct iser_tx_desc *tx_desc)
return cur_wr; return cur_wr;
} }
static inline struct iser_conn *
to_iser_conn(struct ib_conn *ib_conn)
{
return container_of(ib_conn, struct iser_conn, ib_conn);
}
static inline struct iser_rx_desc *
iser_rx(struct ib_cqe *cqe)
{
return container_of(cqe, struct iser_rx_desc, cqe);
}
static inline struct iser_tx_desc *
iser_tx(struct ib_cqe *cqe)
{
return container_of(cqe, struct iser_tx_desc, cqe);
}
static inline struct iser_login_desc *
iser_login(struct ib_cqe *cqe)
{
return container_of(cqe, struct iser_login_desc, cqe);
}
#endif #endif
...@@ -67,6 +67,11 @@ static struct iser_reg_ops fmr_ops = { ...@@ -67,6 +67,11 @@ static struct iser_reg_ops fmr_ops = {
.reg_desc_put = iser_reg_desc_put_fmr, .reg_desc_put = iser_reg_desc_put_fmr,
}; };
void iser_reg_comp(struct ib_cq *cq, struct ib_wc *wc)
{
iser_err_comp(wc, "memreg");
}
int iser_assign_reg_ops(struct iser_device *device) int iser_assign_reg_ops(struct iser_device *device)
{ {
struct ib_device *ib_dev = device->ib_device; struct ib_device *ib_dev = device->ib_device;
...@@ -413,12 +418,14 @@ iser_set_prot_checks(struct scsi_cmnd *sc, u8 *mask) ...@@ -413,12 +418,14 @@ iser_set_prot_checks(struct scsi_cmnd *sc, u8 *mask)
} }
static void static void
iser_inv_rkey(struct ib_send_wr *inv_wr, struct ib_mr *mr) iser_inv_rkey(struct ib_send_wr *inv_wr,
struct ib_mr *mr,
struct ib_cqe *cqe)
{ {
u32 rkey; u32 rkey;
inv_wr->opcode = IB_WR_LOCAL_INV; inv_wr->opcode = IB_WR_LOCAL_INV;
inv_wr->wr_id = ISER_FASTREG_LI_WRID; inv_wr->wr_cqe = cqe;
inv_wr->ex.invalidate_rkey = mr->rkey; inv_wr->ex.invalidate_rkey = mr->rkey;
inv_wr->send_flags = 0; inv_wr->send_flags = 0;
inv_wr->num_sge = 0; inv_wr->num_sge = 0;
...@@ -436,6 +443,7 @@ iser_reg_sig_mr(struct iscsi_iser_task *iser_task, ...@@ -436,6 +443,7 @@ iser_reg_sig_mr(struct iscsi_iser_task *iser_task,
{ {
struct iser_tx_desc *tx_desc = &iser_task->desc; struct iser_tx_desc *tx_desc = &iser_task->desc;
struct ib_sig_attrs *sig_attrs = &tx_desc->sig_attrs; struct ib_sig_attrs *sig_attrs = &tx_desc->sig_attrs;
struct ib_cqe *cqe = &iser_task->iser_conn->ib_conn.reg_cqe;
struct ib_sig_handover_wr *wr; struct ib_sig_handover_wr *wr;
int ret; int ret;
...@@ -447,11 +455,11 @@ iser_reg_sig_mr(struct iscsi_iser_task *iser_task, ...@@ -447,11 +455,11 @@ iser_reg_sig_mr(struct iscsi_iser_task *iser_task,
iser_set_prot_checks(iser_task->sc, &sig_attrs->check_mask); iser_set_prot_checks(iser_task->sc, &sig_attrs->check_mask);
if (!pi_ctx->sig_mr_valid) if (!pi_ctx->sig_mr_valid)
iser_inv_rkey(iser_tx_next_wr(tx_desc), pi_ctx->sig_mr); iser_inv_rkey(iser_tx_next_wr(tx_desc), pi_ctx->sig_mr, cqe);
wr = sig_handover_wr(iser_tx_next_wr(tx_desc)); wr = sig_handover_wr(iser_tx_next_wr(tx_desc));
wr->wr.opcode = IB_WR_REG_SIG_MR; wr->wr.opcode = IB_WR_REG_SIG_MR;
wr->wr.wr_id = ISER_FASTREG_LI_WRID; wr->wr.wr_cqe = cqe;
wr->wr.sg_list = &data_reg->sge; wr->wr.sg_list = &data_reg->sge;
wr->wr.num_sge = 1; wr->wr.num_sge = 1;
wr->wr.send_flags = 0; wr->wr.send_flags = 0;
...@@ -484,12 +492,13 @@ static int iser_fast_reg_mr(struct iscsi_iser_task *iser_task, ...@@ -484,12 +492,13 @@ static int iser_fast_reg_mr(struct iscsi_iser_task *iser_task,
struct iser_mem_reg *reg) struct iser_mem_reg *reg)
{ {
struct iser_tx_desc *tx_desc = &iser_task->desc; struct iser_tx_desc *tx_desc = &iser_task->desc;
struct ib_cqe *cqe = &iser_task->iser_conn->ib_conn.reg_cqe;
struct ib_mr *mr = rsc->mr; struct ib_mr *mr = rsc->mr;
struct ib_reg_wr *wr; struct ib_reg_wr *wr;
int n; int n;
if (!rsc->mr_valid) if (!rsc->mr_valid)
iser_inv_rkey(iser_tx_next_wr(tx_desc), mr); iser_inv_rkey(iser_tx_next_wr(tx_desc), mr, cqe);
n = ib_map_mr_sg(mr, mem->sg, mem->size, SIZE_4K); n = ib_map_mr_sg(mr, mem->sg, mem->size, SIZE_4K);
if (unlikely(n != mem->size)) { if (unlikely(n != mem->size)) {
...@@ -500,7 +509,7 @@ static int iser_fast_reg_mr(struct iscsi_iser_task *iser_task, ...@@ -500,7 +509,7 @@ static int iser_fast_reg_mr(struct iscsi_iser_task *iser_task,
wr = reg_wr(iser_tx_next_wr(tx_desc)); wr = reg_wr(iser_tx_next_wr(tx_desc));
wr->wr.opcode = IB_WR_REG_MR; wr->wr.opcode = IB_WR_REG_MR;
wr->wr.wr_id = ISER_FASTREG_LI_WRID; wr->wr.wr_cqe = cqe;
wr->wr.send_flags = 0; wr->wr.send_flags = 0;
wr->wr.num_sge = 0; wr->wr.num_sge = 0;
wr->mr = mr; wr->mr = mr;
......
This diff is collapsed.
This diff is collapsed.
...@@ -66,11 +66,6 @@ enum { ...@@ -66,11 +66,6 @@ enum {
SRP_TAG_TSK_MGMT = 1U << 31, SRP_TAG_TSK_MGMT = 1U << 31,
SRP_MAX_PAGES_PER_MR = 512, SRP_MAX_PAGES_PER_MR = 512,
LOCAL_INV_WR_ID_MASK = 1,
FAST_REG_WR_ID_MASK = 2,
SRP_LAST_WR_ID = 0xfffffffcU,
}; };
enum srp_target_state { enum srp_target_state {
...@@ -128,6 +123,7 @@ struct srp_request { ...@@ -128,6 +123,7 @@ struct srp_request {
struct srp_direct_buf *indirect_desc; struct srp_direct_buf *indirect_desc;
dma_addr_t indirect_dma_addr; dma_addr_t indirect_dma_addr;
short nmdesc; short nmdesc;
struct ib_cqe reg_cqe;
}; };
/** /**
...@@ -231,6 +227,7 @@ struct srp_iu { ...@@ -231,6 +227,7 @@ struct srp_iu {
void *buf; void *buf;
size_t size; size_t size;
enum dma_data_direction direction; enum dma_data_direction direction;
struct ib_cqe cqe;
}; };
/** /**
......
This diff is collapsed.
...@@ -128,36 +128,6 @@ enum { ...@@ -128,36 +128,6 @@ enum {
DEFAULT_MAX_RDMA_SIZE = 65536, DEFAULT_MAX_RDMA_SIZE = 65536,
}; };
enum srpt_opcode {
SRPT_RECV,
SRPT_SEND,
SRPT_RDMA_MID,
SRPT_RDMA_ABORT,
SRPT_RDMA_READ_LAST,
SRPT_RDMA_WRITE_LAST,
};
static inline u64 encode_wr_id(u8 opcode, u32 idx)
{
return ((u64)opcode << 32) | idx;
}
static inline enum srpt_opcode opcode_from_wr_id(u64 wr_id)
{
return wr_id >> 32;
}
static inline u32 idx_from_wr_id(u64 wr_id)
{
return (u32)wr_id;
}
struct rdma_iu {
u64 raddr;
u32 rkey;
struct ib_sge *sge;
u32 sge_cnt;
int mem_id;
};
/** /**
* enum srpt_command_state - SCSI command state managed by SRPT. * enum srpt_command_state - SCSI command state managed by SRPT.
* @SRPT_STATE_NEW: New command arrived and is being processed. * @SRPT_STATE_NEW: New command arrived and is being processed.
...@@ -189,6 +159,7 @@ enum srpt_command_state { ...@@ -189,6 +159,7 @@ enum srpt_command_state {
* @index: Index of the I/O context in its ioctx_ring array. * @index: Index of the I/O context in its ioctx_ring array.
*/ */
struct srpt_ioctx { struct srpt_ioctx {
struct ib_cqe cqe;
void *buf; void *buf;
dma_addr_t dma; dma_addr_t dma;
uint32_t index; uint32_t index;
...@@ -215,32 +186,30 @@ struct srpt_recv_ioctx { ...@@ -215,32 +186,30 @@ struct srpt_recv_ioctx {
* @sg: Pointer to sg-list associated with this I/O context. * @sg: Pointer to sg-list associated with this I/O context.
* @sg_cnt: SG-list size. * @sg_cnt: SG-list size.
* @mapped_sg_count: ib_dma_map_sg() return value. * @mapped_sg_count: ib_dma_map_sg() return value.
* @n_rdma_ius: Number of elements in the rdma_ius array. * @n_rdma_wrs: Number of elements in the rdma_wrs array.
* @rdma_ius: Array with information about the RDMA mapping. * @rdma_wrs: Array with information about the RDMA mapping.
* @tag: Tag of the received SRP information unit. * @tag: Tag of the received SRP information unit.
* @spinlock: Protects 'state'. * @spinlock: Protects 'state'.
* @state: I/O context state. * @state: I/O context state.
* @rdma_aborted: If initiating a multipart RDMA transfer failed, whether
* the already initiated transfers have finished.
* @cmd: Target core command data structure. * @cmd: Target core command data structure.
* @sense_data: SCSI sense data. * @sense_data: SCSI sense data.
*/ */
struct srpt_send_ioctx { struct srpt_send_ioctx {
struct srpt_ioctx ioctx; struct srpt_ioctx ioctx;
struct srpt_rdma_ch *ch; struct srpt_rdma_ch *ch;
struct rdma_iu *rdma_ius; struct ib_rdma_wr *rdma_wrs;
struct ib_cqe rdma_cqe;
struct srp_direct_buf *rbufs; struct srp_direct_buf *rbufs;
struct srp_direct_buf single_rbuf; struct srp_direct_buf single_rbuf;
struct scatterlist *sg; struct scatterlist *sg;
struct list_head free_list; struct list_head free_list;
spinlock_t spinlock; spinlock_t spinlock;
enum srpt_command_state state; enum srpt_command_state state;
bool rdma_aborted;
struct se_cmd cmd; struct se_cmd cmd;
struct completion tx_done; struct completion tx_done;
int sg_cnt; int sg_cnt;
int mapped_sg_count; int mapped_sg_count;
u16 n_rdma_ius; u16 n_rdma_wrs;
u8 n_rdma; u8 n_rdma;
u8 n_rbuf; u8 n_rbuf;
bool queue_status_only; bool queue_status_only;
...@@ -267,9 +236,6 @@ enum rdma_ch_state { ...@@ -267,9 +236,6 @@ enum rdma_ch_state {
/** /**
* struct srpt_rdma_ch - RDMA channel. * struct srpt_rdma_ch - RDMA channel.
* @wait_queue: Allows the kernel thread to wait for more work.
* @thread: Kernel thread that processes the IB queues associated with
* the channel.
* @cm_id: IB CM ID associated with the channel. * @cm_id: IB CM ID associated with the channel.
* @qp: IB queue pair used for communicating over this channel. * @qp: IB queue pair used for communicating over this channel.
* @cq: IB completion queue for this channel. * @cq: IB completion queue for this channel.
...@@ -299,8 +265,6 @@ enum rdma_ch_state { ...@@ -299,8 +265,6 @@ enum rdma_ch_state {
* @release_done: Enables waiting for srpt_release_channel() completion. * @release_done: Enables waiting for srpt_release_channel() completion.
*/ */
struct srpt_rdma_ch { struct srpt_rdma_ch {
wait_queue_head_t wait_queue;
struct task_struct *thread;
struct ib_cm_id *cm_id; struct ib_cm_id *cm_id;
struct ib_qp *qp; struct ib_qp *qp;
struct ib_cq *cq; struct ib_cq *cq;
......
...@@ -1104,6 +1104,7 @@ config SCSI_IPR ...@@ -1104,6 +1104,7 @@ config SCSI_IPR
tristate "IBM Power Linux RAID adapter support" tristate "IBM Power Linux RAID adapter support"
depends on PCI && SCSI && ATA depends on PCI && SCSI && ATA
select FW_LOADER select FW_LOADER
select IRQ_POLL
---help--- ---help---
This driver supports the IBM Power Linux family RAID adapters. This driver supports the IBM Power Linux family RAID adapters.
This includes IBM pSeries 5712, 5703, 5709, and 570A, as well This includes IBM pSeries 5712, 5703, 5709, and 570A, as well
......
...@@ -3,6 +3,7 @@ config BE2ISCSI ...@@ -3,6 +3,7 @@ config BE2ISCSI
depends on PCI && SCSI && NET depends on PCI && SCSI && NET
select SCSI_ISCSI_ATTRS select SCSI_ISCSI_ATTRS
select ISCSI_BOOT_SYSFS select ISCSI_BOOT_SYSFS
select IRQ_POLL
help help
This driver implements the iSCSI functionality for Emulex This driver implements the iSCSI functionality for Emulex
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#include <linux/blk-iopoll.h> #include <linux/irq_poll.h>
#define FW_VER_LEN 32 #define FW_VER_LEN 32
#define MCC_Q_LEN 128 #define MCC_Q_LEN 128
#define MCC_CQ_LEN 256 #define MCC_CQ_LEN 256
...@@ -101,7 +101,7 @@ struct be_eq_obj { ...@@ -101,7 +101,7 @@ struct be_eq_obj {
struct beiscsi_hba *phba; struct beiscsi_hba *phba;
struct be_queue_info *cq; struct be_queue_info *cq;
struct work_struct work_cqs; /* Work Item */ struct work_struct work_cqs; /* Work Item */
struct blk_iopoll iopoll; struct irq_poll iopoll;
}; };
struct be_mcc_obj { struct be_mcc_obj {
......
...@@ -1292,9 +1292,9 @@ static void beiscsi_flush_cq(struct beiscsi_hba *phba) ...@@ -1292,9 +1292,9 @@ static void beiscsi_flush_cq(struct beiscsi_hba *phba)
for (i = 0; i < phba->num_cpus; i++) { for (i = 0; i < phba->num_cpus; i++) {
pbe_eq = &phwi_context->be_eq[i]; pbe_eq = &phwi_context->be_eq[i];
blk_iopoll_disable(&pbe_eq->iopoll); irq_poll_disable(&pbe_eq->iopoll);
beiscsi_process_cq(pbe_eq); beiscsi_process_cq(pbe_eq);
blk_iopoll_enable(&pbe_eq->iopoll); irq_poll_enable(&pbe_eq->iopoll);
} }
} }
......
...@@ -910,8 +910,7 @@ static irqreturn_t be_isr_msix(int irq, void *dev_id) ...@@ -910,8 +910,7 @@ static irqreturn_t be_isr_msix(int irq, void *dev_id)
num_eq_processed = 0; num_eq_processed = 0;
while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32]
& EQE_VALID_MASK) { & EQE_VALID_MASK) {
if (!blk_iopoll_sched_prep(&pbe_eq->iopoll)) irq_poll_sched(&pbe_eq->iopoll);
blk_iopoll_sched(&pbe_eq->iopoll);
AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
queue_tail_inc(eq); queue_tail_inc(eq);
...@@ -972,8 +971,7 @@ static irqreturn_t be_isr(int irq, void *dev_id) ...@@ -972,8 +971,7 @@ static irqreturn_t be_isr(int irq, void *dev_id)
spin_unlock_irqrestore(&phba->isr_lock, flags); spin_unlock_irqrestore(&phba->isr_lock, flags);
num_mcceq_processed++; num_mcceq_processed++;
} else { } else {
if (!blk_iopoll_sched_prep(&pbe_eq->iopoll)) irq_poll_sched(&pbe_eq->iopoll);
blk_iopoll_sched(&pbe_eq->iopoll);
num_ioeq_processed++; num_ioeq_processed++;
} }
AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
...@@ -2295,7 +2293,7 @@ void beiscsi_process_all_cqs(struct work_struct *work) ...@@ -2295,7 +2293,7 @@ void beiscsi_process_all_cqs(struct work_struct *work)
hwi_ring_eq_db(phba, pbe_eq->q.id, 0, 0, 1, 1); hwi_ring_eq_db(phba, pbe_eq->q.id, 0, 0, 1, 1);
} }
static int be_iopoll(struct blk_iopoll *iop, int budget) static int be_iopoll(struct irq_poll *iop, int budget)
{ {
unsigned int ret; unsigned int ret;
struct beiscsi_hba *phba; struct beiscsi_hba *phba;
...@@ -2306,7 +2304,7 @@ static int be_iopoll(struct blk_iopoll *iop, int budget) ...@@ -2306,7 +2304,7 @@ static int be_iopoll(struct blk_iopoll *iop, int budget)
pbe_eq->cq_count += ret; pbe_eq->cq_count += ret;
if (ret < budget) { if (ret < budget) {
phba = pbe_eq->phba; phba = pbe_eq->phba;
blk_iopoll_complete(iop); irq_poll_complete(iop);
beiscsi_log(phba, KERN_INFO, beiscsi_log(phba, KERN_INFO,
BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO, BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO,
"BM_%d : rearm pbe_eq->q.id =%d\n", "BM_%d : rearm pbe_eq->q.id =%d\n",
...@@ -5293,7 +5291,7 @@ static void beiscsi_quiesce(struct beiscsi_hba *phba, ...@@ -5293,7 +5291,7 @@ static void beiscsi_quiesce(struct beiscsi_hba *phba,
for (i = 0; i < phba->num_cpus; i++) { for (i = 0; i < phba->num_cpus; i++) {
pbe_eq = &phwi_context->be_eq[i]; pbe_eq = &phwi_context->be_eq[i];
blk_iopoll_disable(&pbe_eq->iopoll); irq_poll_disable(&pbe_eq->iopoll);
} }
if (unload_state == BEISCSI_CLEAN_UNLOAD) { if (unload_state == BEISCSI_CLEAN_UNLOAD) {
...@@ -5579,9 +5577,8 @@ static void beiscsi_eeh_resume(struct pci_dev *pdev) ...@@ -5579,9 +5577,8 @@ static void beiscsi_eeh_resume(struct pci_dev *pdev)
for (i = 0; i < phba->num_cpus; i++) { for (i = 0; i < phba->num_cpus; i++) {
pbe_eq = &phwi_context->be_eq[i]; pbe_eq = &phwi_context->be_eq[i];
blk_iopoll_init(&pbe_eq->iopoll, be_iopoll_budget, irq_poll_init(&pbe_eq->iopoll, be_iopoll_budget,
be_iopoll); be_iopoll);
blk_iopoll_enable(&pbe_eq->iopoll);
} }
i = (phba->msix_enabled) ? i : 0; i = (phba->msix_enabled) ? i : 0;
...@@ -5752,9 +5749,8 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, ...@@ -5752,9 +5749,8 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev,
for (i = 0; i < phba->num_cpus; i++) { for (i = 0; i < phba->num_cpus; i++) {
pbe_eq = &phwi_context->be_eq[i]; pbe_eq = &phwi_context->be_eq[i];
blk_iopoll_init(&pbe_eq->iopoll, be_iopoll_budget, irq_poll_init(&pbe_eq->iopoll, be_iopoll_budget,
be_iopoll); be_iopoll);
blk_iopoll_enable(&pbe_eq->iopoll);
} }
i = (phba->msix_enabled) ? i : 0; i = (phba->msix_enabled) ? i : 0;
...@@ -5795,7 +5791,7 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, ...@@ -5795,7 +5791,7 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev,
destroy_workqueue(phba->wq); destroy_workqueue(phba->wq);
for (i = 0; i < phba->num_cpus; i++) { for (i = 0; i < phba->num_cpus; i++) {
pbe_eq = &phwi_context->be_eq[i]; pbe_eq = &phwi_context->be_eq[i];
blk_iopoll_disable(&pbe_eq->iopoll); irq_poll_disable(&pbe_eq->iopoll);
} }
free_twq: free_twq:
beiscsi_clean_port(phba); beiscsi_clean_port(phba);
......
...@@ -3638,7 +3638,7 @@ static struct device_attribute ipr_ioa_reset_attr = { ...@@ -3638,7 +3638,7 @@ static struct device_attribute ipr_ioa_reset_attr = {
.store = ipr_store_reset_adapter .store = ipr_store_reset_adapter
}; };
static int ipr_iopoll(struct blk_iopoll *iop, int budget); static int ipr_iopoll(struct irq_poll *iop, int budget);
/** /**
* ipr_show_iopoll_weight - Show ipr polling mode * ipr_show_iopoll_weight - Show ipr polling mode
* @dev: class device struct * @dev: class device struct
...@@ -3681,34 +3681,33 @@ static ssize_t ipr_store_iopoll_weight(struct device *dev, ...@@ -3681,34 +3681,33 @@ static ssize_t ipr_store_iopoll_weight(struct device *dev,
int i; int i;
if (!ioa_cfg->sis64) { if (!ioa_cfg->sis64) {
dev_info(&ioa_cfg->pdev->dev, "blk-iopoll not supported on this adapter\n"); dev_info(&ioa_cfg->pdev->dev, "irq_poll not supported on this adapter\n");
return -EINVAL; return -EINVAL;
} }
if (kstrtoul(buf, 10, &user_iopoll_weight)) if (kstrtoul(buf, 10, &user_iopoll_weight))
return -EINVAL; return -EINVAL;
if (user_iopoll_weight > 256) { if (user_iopoll_weight > 256) {
dev_info(&ioa_cfg->pdev->dev, "Invalid blk-iopoll weight. It must be less than 256\n"); dev_info(&ioa_cfg->pdev->dev, "Invalid irq_poll weight. It must be less than 256\n");
return -EINVAL; return -EINVAL;
} }
if (user_iopoll_weight == ioa_cfg->iopoll_weight) { if (user_iopoll_weight == ioa_cfg->iopoll_weight) {
dev_info(&ioa_cfg->pdev->dev, "Current blk-iopoll weight has the same weight\n"); dev_info(&ioa_cfg->pdev->dev, "Current irq_poll weight has the same weight\n");
return strlen(buf); return strlen(buf);
} }
if (ioa_cfg->iopoll_weight && ioa_cfg->sis64 && ioa_cfg->nvectors > 1) { if (ioa_cfg->iopoll_weight && ioa_cfg->sis64 && ioa_cfg->nvectors > 1) {
for (i = 1; i < ioa_cfg->hrrq_num; i++) for (i = 1; i < ioa_cfg->hrrq_num; i++)
blk_iopoll_disable(&ioa_cfg->hrrq[i].iopoll); irq_poll_disable(&ioa_cfg->hrrq[i].iopoll);
} }
spin_lock_irqsave(shost->host_lock, lock_flags); spin_lock_irqsave(shost->host_lock, lock_flags);
ioa_cfg->iopoll_weight = user_iopoll_weight; ioa_cfg->iopoll_weight = user_iopoll_weight;
if (ioa_cfg->iopoll_weight && ioa_cfg->sis64 && ioa_cfg->nvectors > 1) { if (ioa_cfg->iopoll_weight && ioa_cfg->sis64 && ioa_cfg->nvectors > 1) {
for (i = 1; i < ioa_cfg->hrrq_num; i++) { for (i = 1; i < ioa_cfg->hrrq_num; i++) {
blk_iopoll_init(&ioa_cfg->hrrq[i].iopoll, irq_poll_init(&ioa_cfg->hrrq[i].iopoll,
ioa_cfg->iopoll_weight, ipr_iopoll); ioa_cfg->iopoll_weight, ipr_iopoll);
blk_iopoll_enable(&ioa_cfg->hrrq[i].iopoll);
} }
} }
spin_unlock_irqrestore(shost->host_lock, lock_flags); spin_unlock_irqrestore(shost->host_lock, lock_flags);
...@@ -5569,7 +5568,7 @@ static int ipr_process_hrrq(struct ipr_hrr_queue *hrr_queue, int budget, ...@@ -5569,7 +5568,7 @@ static int ipr_process_hrrq(struct ipr_hrr_queue *hrr_queue, int budget,
return num_hrrq; return num_hrrq;
} }
static int ipr_iopoll(struct blk_iopoll *iop, int budget) static int ipr_iopoll(struct irq_poll *iop, int budget)
{ {
struct ipr_ioa_cfg *ioa_cfg; struct ipr_ioa_cfg *ioa_cfg;
struct ipr_hrr_queue *hrrq; struct ipr_hrr_queue *hrrq;
...@@ -5585,7 +5584,7 @@ static int ipr_iopoll(struct blk_iopoll *iop, int budget) ...@@ -5585,7 +5584,7 @@ static int ipr_iopoll(struct blk_iopoll *iop, int budget)
completed_ops = ipr_process_hrrq(hrrq, budget, &doneq); completed_ops = ipr_process_hrrq(hrrq, budget, &doneq);
if (completed_ops < budget) if (completed_ops < budget)
blk_iopoll_complete(iop); irq_poll_complete(iop);
spin_unlock_irqrestore(hrrq->lock, hrrq_flags); spin_unlock_irqrestore(hrrq->lock, hrrq_flags);
list_for_each_entry_safe(ipr_cmd, temp, &doneq, queue) { list_for_each_entry_safe(ipr_cmd, temp, &doneq, queue) {
...@@ -5693,8 +5692,7 @@ static irqreturn_t ipr_isr_mhrrq(int irq, void *devp) ...@@ -5693,8 +5692,7 @@ static irqreturn_t ipr_isr_mhrrq(int irq, void *devp)
if (ioa_cfg->iopoll_weight && ioa_cfg->sis64 && ioa_cfg->nvectors > 1) { if (ioa_cfg->iopoll_weight && ioa_cfg->sis64 && ioa_cfg->nvectors > 1) {
if ((be32_to_cpu(*hrrq->hrrq_curr) & IPR_HRRQ_TOGGLE_BIT) == if ((be32_to_cpu(*hrrq->hrrq_curr) & IPR_HRRQ_TOGGLE_BIT) ==
hrrq->toggle_bit) { hrrq->toggle_bit) {
if (!blk_iopoll_sched_prep(&hrrq->iopoll)) irq_poll_sched(&hrrq->iopoll);
blk_iopoll_sched(&hrrq->iopoll);
spin_unlock_irqrestore(hrrq->lock, hrrq_flags); spin_unlock_irqrestore(hrrq->lock, hrrq_flags);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -10405,9 +10403,8 @@ static int ipr_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) ...@@ -10405,9 +10403,8 @@ static int ipr_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
if (ioa_cfg->iopoll_weight && ioa_cfg->sis64 && ioa_cfg->nvectors > 1) { if (ioa_cfg->iopoll_weight && ioa_cfg->sis64 && ioa_cfg->nvectors > 1) {
for (i = 1; i < ioa_cfg->hrrq_num; i++) { for (i = 1; i < ioa_cfg->hrrq_num; i++) {
blk_iopoll_init(&ioa_cfg->hrrq[i].iopoll, irq_poll_init(&ioa_cfg->hrrq[i].iopoll,
ioa_cfg->iopoll_weight, ipr_iopoll); ioa_cfg->iopoll_weight, ipr_iopoll);
blk_iopoll_enable(&ioa_cfg->hrrq[i].iopoll);
} }
} }
...@@ -10436,7 +10433,7 @@ static void ipr_shutdown(struct pci_dev *pdev) ...@@ -10436,7 +10433,7 @@ static void ipr_shutdown(struct pci_dev *pdev)
if (ioa_cfg->iopoll_weight && ioa_cfg->sis64 && ioa_cfg->nvectors > 1) { if (ioa_cfg->iopoll_weight && ioa_cfg->sis64 && ioa_cfg->nvectors > 1) {
ioa_cfg->iopoll_weight = 0; ioa_cfg->iopoll_weight = 0;
for (i = 1; i < ioa_cfg->hrrq_num; i++) for (i = 1; i < ioa_cfg->hrrq_num; i++)
blk_iopoll_disable(&ioa_cfg->hrrq[i].iopoll); irq_poll_disable(&ioa_cfg->hrrq[i].iopoll);
} }
while (ioa_cfg->in_reset_reload) { while (ioa_cfg->in_reset_reload) {
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
#include <linux/libata.h> #include <linux/libata.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/kref.h> #include <linux/kref.h>
#include <linux/blk-iopoll.h> #include <linux/irq_poll.h>
#include <scsi/scsi.h> #include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h> #include <scsi/scsi_cmnd.h>
...@@ -517,7 +517,7 @@ struct ipr_hrr_queue { ...@@ -517,7 +517,7 @@ struct ipr_hrr_queue {
u8 allow_cmds:1; u8 allow_cmds:1;
u8 removing_ioa:1; u8 removing_ioa:1;
struct blk_iopoll iopoll; struct irq_poll iopoll;
}; };
/* Command packet structure */ /* Command packet structure */
......
#ifndef BLK_IOPOLL_H
#define BLK_IOPOLL_H
struct blk_iopoll;
typedef int (blk_iopoll_fn)(struct blk_iopoll *, int);
struct blk_iopoll {
struct list_head list;
unsigned long state;
unsigned long data;
int weight;
int max;
blk_iopoll_fn *poll;
};
enum {
IOPOLL_F_SCHED = 0,
IOPOLL_F_DISABLE = 1,
};
/*
* Returns 0 if we successfully set the IOPOLL_F_SCHED bit, indicating
* that we were the first to acquire this iop for scheduling. If this iop
* is currently disabled, return "failure".
*/
static inline int blk_iopoll_sched_prep(struct blk_iopoll *iop)
{
if (!test_bit(IOPOLL_F_DISABLE, &iop->state))
return test_and_set_bit(IOPOLL_F_SCHED, &iop->state);
return 1;
}
static inline int blk_iopoll_disable_pending(struct blk_iopoll *iop)
{
return test_bit(IOPOLL_F_DISABLE, &iop->state);
}
extern void blk_iopoll_sched(struct blk_iopoll *);
extern void blk_iopoll_init(struct blk_iopoll *, int, blk_iopoll_fn *);
extern void blk_iopoll_complete(struct blk_iopoll *);
extern void __blk_iopoll_complete(struct blk_iopoll *);
extern void blk_iopoll_enable(struct blk_iopoll *);
extern void blk_iopoll_disable(struct blk_iopoll *);
#endif
...@@ -412,7 +412,7 @@ enum ...@@ -412,7 +412,7 @@ enum
NET_TX_SOFTIRQ, NET_TX_SOFTIRQ,
NET_RX_SOFTIRQ, NET_RX_SOFTIRQ,
BLOCK_SOFTIRQ, BLOCK_SOFTIRQ,
BLOCK_IOPOLL_SOFTIRQ, IRQ_POLL_SOFTIRQ,
TASKLET_SOFTIRQ, TASKLET_SOFTIRQ,
SCHED_SOFTIRQ, SCHED_SOFTIRQ,
HRTIMER_SOFTIRQ, /* Unused, but kept as tools rely on the HRTIMER_SOFTIRQ, /* Unused, but kept as tools rely on the
......
#ifndef IRQ_POLL_H
#define IRQ_POLL_H
struct irq_poll;
typedef int (irq_poll_fn)(struct irq_poll *, int);
struct irq_poll {
struct list_head list;
unsigned long state;
int weight;
irq_poll_fn *poll;
};
enum {
IRQ_POLL_F_SCHED = 0,
IRQ_POLL_F_DISABLE = 1,
};
extern void irq_poll_sched(struct irq_poll *);
extern void irq_poll_init(struct irq_poll *, int, irq_poll_fn *);
extern void irq_poll_complete(struct irq_poll *);
extern void irq_poll_enable(struct irq_poll *);
extern void irq_poll_disable(struct irq_poll *);
#endif
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/socket.h> #include <linux/socket.h>
#include <linux/irq_poll.h>
#include <uapi/linux/if_ether.h> #include <uapi/linux/if_ether.h>
#include <linux/atomic.h> #include <linux/atomic.h>
...@@ -56,6 +57,7 @@ ...@@ -56,6 +57,7 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
extern struct workqueue_struct *ib_wq; extern struct workqueue_struct *ib_wq;
extern struct workqueue_struct *ib_comp_wq;
union ib_gid { union ib_gid {
u8 raw[16]; u8 raw[16];
...@@ -758,7 +760,10 @@ enum ib_wc_flags { ...@@ -758,7 +760,10 @@ enum ib_wc_flags {
}; };
struct ib_wc { struct ib_wc {
u64 wr_id; union {
u64 wr_id;
struct ib_cqe *wr_cqe;
};
enum ib_wc_status status; enum ib_wc_status status;
enum ib_wc_opcode opcode; enum ib_wc_opcode opcode;
u32 vendor_err; u32 vendor_err;
...@@ -1079,9 +1084,16 @@ struct ib_mw_bind_info { ...@@ -1079,9 +1084,16 @@ struct ib_mw_bind_info {
int mw_access_flags; int mw_access_flags;
}; };
struct ib_cqe {
void (*done)(struct ib_cq *cq, struct ib_wc *wc);
};
struct ib_send_wr { struct ib_send_wr {
struct ib_send_wr *next; struct ib_send_wr *next;
u64 wr_id; union {
u64 wr_id;
struct ib_cqe *wr_cqe;
};
struct ib_sge *sg_list; struct ib_sge *sg_list;
int num_sge; int num_sge;
enum ib_wr_opcode opcode; enum ib_wr_opcode opcode;
...@@ -1175,7 +1187,10 @@ static inline struct ib_sig_handover_wr *sig_handover_wr(struct ib_send_wr *wr) ...@@ -1175,7 +1187,10 @@ static inline struct ib_sig_handover_wr *sig_handover_wr(struct ib_send_wr *wr)
struct ib_recv_wr { struct ib_recv_wr {
struct ib_recv_wr *next; struct ib_recv_wr *next;
u64 wr_id; union {
u64 wr_id;
struct ib_cqe *wr_cqe;
};
struct ib_sge *sg_list; struct ib_sge *sg_list;
int num_sge; int num_sge;
}; };
...@@ -1307,6 +1322,12 @@ struct ib_ah { ...@@ -1307,6 +1322,12 @@ struct ib_ah {
typedef void (*ib_comp_handler)(struct ib_cq *cq, void *cq_context); typedef void (*ib_comp_handler)(struct ib_cq *cq, void *cq_context);
enum ib_poll_context {
IB_POLL_DIRECT, /* caller context, no hw completions */
IB_POLL_SOFTIRQ, /* poll from softirq context */
IB_POLL_WORKQUEUE, /* poll from workqueue */
};
struct ib_cq { struct ib_cq {
struct ib_device *device; struct ib_device *device;
struct ib_uobject *uobject; struct ib_uobject *uobject;
...@@ -1315,6 +1336,12 @@ struct ib_cq { ...@@ -1315,6 +1336,12 @@ struct ib_cq {
void *cq_context; void *cq_context;
int cqe; int cqe;
atomic_t usecnt; /* count number of work queues */ atomic_t usecnt; /* count number of work queues */
enum ib_poll_context poll_ctx;
struct ib_wc *wc;
union {
struct irq_poll iop;
struct work_struct work;
};
}; };
struct ib_srq { struct ib_srq {
...@@ -2452,6 +2479,11 @@ static inline int ib_post_recv(struct ib_qp *qp, ...@@ -2452,6 +2479,11 @@ static inline int ib_post_recv(struct ib_qp *qp,
return qp->device->post_recv(qp, recv_wr, bad_recv_wr); return qp->device->post_recv(qp, recv_wr, bad_recv_wr);
} }
struct ib_cq *ib_alloc_cq(struct ib_device *dev, void *private,
int nr_cqe, int comp_vector, enum ib_poll_context poll_ctx);
void ib_free_cq(struct ib_cq *cq);
int ib_process_cq_direct(struct ib_cq *cq, int budget);
/** /**
* ib_create_cq - Creates a CQ on the specified device. * ib_create_cq - Creates a CQ on the specified device.
* @device: The device on which to create the CQ. * @device: The device on which to create the CQ.
......
...@@ -15,7 +15,7 @@ struct softirq_action; ...@@ -15,7 +15,7 @@ struct softirq_action;
softirq_name(NET_TX) \ softirq_name(NET_TX) \
softirq_name(NET_RX) \ softirq_name(NET_RX) \
softirq_name(BLOCK) \ softirq_name(BLOCK) \
softirq_name(BLOCK_IOPOLL) \ softirq_name(IRQ_POLL) \
softirq_name(TASKLET) \ softirq_name(TASKLET) \
softirq_name(SCHED) \ softirq_name(SCHED) \
softirq_name(HRTIMER) \ softirq_name(HRTIMER) \
......
...@@ -475,6 +475,11 @@ config DDR ...@@ -475,6 +475,11 @@ config DDR
information. This data is useful for drivers handling information. This data is useful for drivers handling
DDR SDRAM controllers. DDR SDRAM controllers.
config IRQ_POLL
bool "IRQ polling library"
help
Helper library to poll interrupt mitigation using polling.
config MPILIB config MPILIB
tristate tristate
select CLZ_TAB select CLZ_TAB
......
...@@ -164,6 +164,7 @@ obj-$(CONFIG_GENERIC_NET_UTILS) += net_utils.o ...@@ -164,6 +164,7 @@ obj-$(CONFIG_GENERIC_NET_UTILS) += net_utils.o
obj-$(CONFIG_SG_SPLIT) += sg_split.o obj-$(CONFIG_SG_SPLIT) += sg_split.o
obj-$(CONFIG_STMP_DEVICE) += stmp_device.o obj-$(CONFIG_STMP_DEVICE) += stmp_device.o
obj-$(CONFIG_IRQ_POLL) += irq_poll.o
libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o \ libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o \
fdt_empty_tree.o fdt_empty_tree.o
......
...@@ -6,84 +6,84 @@ ...@@ -6,84 +6,84 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/bio.h> #include <linux/bio.h>
#include <linux/blkdev.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/blk-iopoll.h> #include <linux/irq_poll.h>
#include <linux/delay.h> #include <linux/delay.h>
#include "blk.h" static unsigned int irq_poll_budget __read_mostly = 256;
static unsigned int blk_iopoll_budget __read_mostly = 256;
static DEFINE_PER_CPU(struct list_head, blk_cpu_iopoll); static DEFINE_PER_CPU(struct list_head, blk_cpu_iopoll);
/** /**
* blk_iopoll_sched - Schedule a run of the iopoll handler * irq_poll_sched - Schedule a run of the iopoll handler
* @iop: The parent iopoll structure * @iop: The parent iopoll structure
* *
* Description: * Description:
* Add this blk_iopoll structure to the pending poll list and trigger the * Add this irq_poll structure to the pending poll list and trigger the
* raise of the blk iopoll softirq. The driver must already have gotten a * raise of the blk iopoll softirq.
* successful return from blk_iopoll_sched_prep() before calling this.
**/ **/
void blk_iopoll_sched(struct blk_iopoll *iop) void irq_poll_sched(struct irq_poll *iop)
{ {
unsigned long flags; unsigned long flags;
if (test_bit(IRQ_POLL_F_DISABLE, &iop->state))
return;
if (!test_and_set_bit(IRQ_POLL_F_SCHED, &iop->state))
return;
local_irq_save(flags); local_irq_save(flags);
list_add_tail(&iop->list, this_cpu_ptr(&blk_cpu_iopoll)); list_add_tail(&iop->list, this_cpu_ptr(&blk_cpu_iopoll));
__raise_softirq_irqoff(BLOCK_IOPOLL_SOFTIRQ); __raise_softirq_irqoff(IRQ_POLL_SOFTIRQ);
local_irq_restore(flags); local_irq_restore(flags);
} }
EXPORT_SYMBOL(blk_iopoll_sched); EXPORT_SYMBOL(irq_poll_sched);
/** /**
* __blk_iopoll_complete - Mark this @iop as un-polled again * __irq_poll_complete - Mark this @iop as un-polled again
* @iop: The parent iopoll structure * @iop: The parent iopoll structure
* *
* Description: * Description:
* See blk_iopoll_complete(). This function must be called with interrupts * See irq_poll_complete(). This function must be called with interrupts
* disabled. * disabled.
**/ **/
void __blk_iopoll_complete(struct blk_iopoll *iop) static void __irq_poll_complete(struct irq_poll *iop)
{ {
list_del(&iop->list); list_del(&iop->list);
smp_mb__before_atomic(); smp_mb__before_atomic();
clear_bit_unlock(IOPOLL_F_SCHED, &iop->state); clear_bit_unlock(IRQ_POLL_F_SCHED, &iop->state);
} }
EXPORT_SYMBOL(__blk_iopoll_complete);
/** /**
* blk_iopoll_complete - Mark this @iop as un-polled again * irq_poll_complete - Mark this @iop as un-polled again
* @iop: The parent iopoll structure * @iop: The parent iopoll structure
* *
* Description: * Description:
* If a driver consumes less than the assigned budget in its run of the * If a driver consumes less than the assigned budget in its run of the
* iopoll handler, it'll end the polled mode by calling this function. The * iopoll handler, it'll end the polled mode by calling this function. The
* iopoll handler will not be invoked again before blk_iopoll_sched_prep() * iopoll handler will not be invoked again before irq_poll_sched()
* is called. * is called.
**/ **/
void blk_iopoll_complete(struct blk_iopoll *iop) void irq_poll_complete(struct irq_poll *iop)
{ {
unsigned long flags; unsigned long flags;
local_irq_save(flags); local_irq_save(flags);
__blk_iopoll_complete(iop); __irq_poll_complete(iop);
local_irq_restore(flags); local_irq_restore(flags);
} }
EXPORT_SYMBOL(blk_iopoll_complete); EXPORT_SYMBOL(irq_poll_complete);
static void blk_iopoll_softirq(struct softirq_action *h) static void irq_poll_softirq(struct softirq_action *h)
{ {
struct list_head *list = this_cpu_ptr(&blk_cpu_iopoll); struct list_head *list = this_cpu_ptr(&blk_cpu_iopoll);
int rearm = 0, budget = blk_iopoll_budget; int rearm = 0, budget = irq_poll_budget;
unsigned long start_time = jiffies; unsigned long start_time = jiffies;
local_irq_disable(); local_irq_disable();
while (!list_empty(list)) { while (!list_empty(list)) {
struct blk_iopoll *iop; struct irq_poll *iop;
int work, weight; int work, weight;
/* /*
...@@ -101,11 +101,11 @@ static void blk_iopoll_softirq(struct softirq_action *h) ...@@ -101,11 +101,11 @@ static void blk_iopoll_softirq(struct softirq_action *h)
* entries to the tail of this list, and only ->poll() * entries to the tail of this list, and only ->poll()
* calls can remove this head entry from the list. * calls can remove this head entry from the list.
*/ */
iop = list_entry(list->next, struct blk_iopoll, list); iop = list_entry(list->next, struct irq_poll, list);
weight = iop->weight; weight = iop->weight;
work = 0; work = 0;
if (test_bit(IOPOLL_F_SCHED, &iop->state)) if (test_bit(IRQ_POLL_F_SCHED, &iop->state))
work = iop->poll(iop, weight); work = iop->poll(iop, weight);
budget -= work; budget -= work;
...@@ -121,72 +121,70 @@ static void blk_iopoll_softirq(struct softirq_action *h) ...@@ -121,72 +121,70 @@ static void blk_iopoll_softirq(struct softirq_action *h)
* move the instance around on the list at-will. * move the instance around on the list at-will.
*/ */
if (work >= weight) { if (work >= weight) {
if (blk_iopoll_disable_pending(iop)) if (test_bit(IRQ_POLL_F_DISABLE, &iop->state))
__blk_iopoll_complete(iop); __irq_poll_complete(iop);
else else
list_move_tail(&iop->list, list); list_move_tail(&iop->list, list);
} }
} }
if (rearm) if (rearm)
__raise_softirq_irqoff(BLOCK_IOPOLL_SOFTIRQ); __raise_softirq_irqoff(IRQ_POLL_SOFTIRQ);
local_irq_enable(); local_irq_enable();
} }
/** /**
* blk_iopoll_disable - Disable iopoll on this @iop * irq_poll_disable - Disable iopoll on this @iop
* @iop: The parent iopoll structure * @iop: The parent iopoll structure
* *
* Description: * Description:
* Disable io polling and wait for any pending callbacks to have completed. * Disable io polling and wait for any pending callbacks to have completed.
**/ **/
void blk_iopoll_disable(struct blk_iopoll *iop) void irq_poll_disable(struct irq_poll *iop)
{ {
set_bit(IOPOLL_F_DISABLE, &iop->state); set_bit(IRQ_POLL_F_DISABLE, &iop->state);
while (test_and_set_bit(IOPOLL_F_SCHED, &iop->state)) while (test_and_set_bit(IRQ_POLL_F_SCHED, &iop->state))
msleep(1); msleep(1);
clear_bit(IOPOLL_F_DISABLE, &iop->state); clear_bit(IRQ_POLL_F_DISABLE, &iop->state);
} }
EXPORT_SYMBOL(blk_iopoll_disable); EXPORT_SYMBOL(irq_poll_disable);
/** /**
* blk_iopoll_enable - Enable iopoll on this @iop * irq_poll_enable - Enable iopoll on this @iop
* @iop: The parent iopoll structure * @iop: The parent iopoll structure
* *
* Description: * Description:
* Enable iopoll on this @iop. Note that the handler run will not be * Enable iopoll on this @iop. Note that the handler run will not be
* scheduled, it will only mark it as active. * scheduled, it will only mark it as active.
**/ **/
void blk_iopoll_enable(struct blk_iopoll *iop) void irq_poll_enable(struct irq_poll *iop)
{ {
BUG_ON(!test_bit(IOPOLL_F_SCHED, &iop->state)); BUG_ON(!test_bit(IRQ_POLL_F_SCHED, &iop->state));
smp_mb__before_atomic(); smp_mb__before_atomic();
clear_bit_unlock(IOPOLL_F_SCHED, &iop->state); clear_bit_unlock(IRQ_POLL_F_SCHED, &iop->state);
} }
EXPORT_SYMBOL(blk_iopoll_enable); EXPORT_SYMBOL(irq_poll_enable);
/** /**
* blk_iopoll_init - Initialize this @iop * irq_poll_init - Initialize this @iop
* @iop: The parent iopoll structure * @iop: The parent iopoll structure
* @weight: The default weight (or command completion budget) * @weight: The default weight (or command completion budget)
* @poll_fn: The handler to invoke * @poll_fn: The handler to invoke
* *
* Description: * Description:
* Initialize this blk_iopoll structure. Before being actively used, the * Initialize and enable this irq_poll structure.
* driver must call blk_iopoll_enable().
**/ **/
void blk_iopoll_init(struct blk_iopoll *iop, int weight, blk_iopoll_fn *poll_fn) void irq_poll_init(struct irq_poll *iop, int weight, irq_poll_fn *poll_fn)
{ {
memset(iop, 0, sizeof(*iop)); memset(iop, 0, sizeof(*iop));
INIT_LIST_HEAD(&iop->list); INIT_LIST_HEAD(&iop->list);
iop->weight = weight; iop->weight = weight;
iop->poll = poll_fn; iop->poll = poll_fn;
set_bit(IOPOLL_F_SCHED, &iop->state);
} }
EXPORT_SYMBOL(blk_iopoll_init); EXPORT_SYMBOL(irq_poll_init);
static int blk_iopoll_cpu_notify(struct notifier_block *self, static int irq_poll_cpu_notify(struct notifier_block *self,
unsigned long action, void *hcpu) unsigned long action, void *hcpu)
{ {
/* /*
...@@ -199,26 +197,26 @@ static int blk_iopoll_cpu_notify(struct notifier_block *self, ...@@ -199,26 +197,26 @@ static int blk_iopoll_cpu_notify(struct notifier_block *self,
local_irq_disable(); local_irq_disable();
list_splice_init(&per_cpu(blk_cpu_iopoll, cpu), list_splice_init(&per_cpu(blk_cpu_iopoll, cpu),
this_cpu_ptr(&blk_cpu_iopoll)); this_cpu_ptr(&blk_cpu_iopoll));
__raise_softirq_irqoff(BLOCK_IOPOLL_SOFTIRQ); __raise_softirq_irqoff(IRQ_POLL_SOFTIRQ);
local_irq_enable(); local_irq_enable();
} }
return NOTIFY_OK; return NOTIFY_OK;
} }
static struct notifier_block blk_iopoll_cpu_notifier = { static struct notifier_block irq_poll_cpu_notifier = {
.notifier_call = blk_iopoll_cpu_notify, .notifier_call = irq_poll_cpu_notify,
}; };
static __init int blk_iopoll_setup(void) static __init int irq_poll_setup(void)
{ {
int i; int i;
for_each_possible_cpu(i) for_each_possible_cpu(i)
INIT_LIST_HEAD(&per_cpu(blk_cpu_iopoll, i)); INIT_LIST_HEAD(&per_cpu(blk_cpu_iopoll, i));
open_softirq(BLOCK_IOPOLL_SOFTIRQ, blk_iopoll_softirq); open_softirq(IRQ_POLL_SOFTIRQ, irq_poll_softirq);
register_hotcpu_notifier(&blk_iopoll_cpu_notifier); register_hotcpu_notifier(&irq_poll_cpu_notifier);
return 0; return 0;
} }
subsys_initcall(blk_iopoll_setup); subsys_initcall(irq_poll_setup);
...@@ -3746,7 +3746,7 @@ static const struct flag flags[] = { ...@@ -3746,7 +3746,7 @@ static const struct flag flags[] = {
{ "NET_TX_SOFTIRQ", 2 }, { "NET_TX_SOFTIRQ", 2 },
{ "NET_RX_SOFTIRQ", 3 }, { "NET_RX_SOFTIRQ", 3 },
{ "BLOCK_SOFTIRQ", 4 }, { "BLOCK_SOFTIRQ", 4 },
{ "BLOCK_IOPOLL_SOFTIRQ", 5 }, { "IRQ_POLL_SOFTIRQ", 5 },
{ "TASKLET_SOFTIRQ", 6 }, { "TASKLET_SOFTIRQ", 6 },
{ "SCHED_SOFTIRQ", 7 }, { "SCHED_SOFTIRQ", 7 },
{ "HRTIMER_SOFTIRQ", 8 }, { "HRTIMER_SOFTIRQ", 8 },
......
...@@ -209,7 +209,7 @@ static const struct flag flags[] = { ...@@ -209,7 +209,7 @@ static const struct flag flags[] = {
{ "NET_TX_SOFTIRQ", 2 }, { "NET_TX_SOFTIRQ", 2 },
{ "NET_RX_SOFTIRQ", 3 }, { "NET_RX_SOFTIRQ", 3 },
{ "BLOCK_SOFTIRQ", 4 }, { "BLOCK_SOFTIRQ", 4 },
{ "BLOCK_IOPOLL_SOFTIRQ", 5 }, { "IRQ_POLL_SOFTIRQ", 5 },
{ "TASKLET_SOFTIRQ", 6 }, { "TASKLET_SOFTIRQ", 6 },
{ "SCHED_SOFTIRQ", 7 }, { "SCHED_SOFTIRQ", 7 },
{ "HRTIMER_SOFTIRQ", 8 }, { "HRTIMER_SOFTIRQ", 8 },
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment