sx8: use a per-host tag_set
The current sx8 code spends a lot of effort dealing with the fact that tags are per-host, but there might be multiple queues. Now that the driver has been converted to blk-mq it can take care of the blk-mq tag_set concept that has been designed just for that. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jens Axboe <axboe@kernel.dk>hifive-unleashed-5.1
parent
cd94c9ed59
commit
72d7ce8eb2
|
@ -243,7 +243,6 @@ struct carm_port {
|
||||||
unsigned int port_no;
|
unsigned int port_no;
|
||||||
struct gendisk *disk;
|
struct gendisk *disk;
|
||||||
struct carm_host *host;
|
struct carm_host *host;
|
||||||
struct blk_mq_tag_set tag_set;
|
|
||||||
|
|
||||||
/* attached device characteristics */
|
/* attached device characteristics */
|
||||||
u64 capacity;
|
u64 capacity;
|
||||||
|
@ -254,13 +253,10 @@ struct carm_port {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct carm_request {
|
struct carm_request {
|
||||||
unsigned int tag;
|
|
||||||
int n_elem;
|
int n_elem;
|
||||||
unsigned int msg_type;
|
unsigned int msg_type;
|
||||||
unsigned int msg_subtype;
|
unsigned int msg_subtype;
|
||||||
unsigned int msg_bucket;
|
unsigned int msg_bucket;
|
||||||
struct request *rq;
|
|
||||||
struct carm_port *port;
|
|
||||||
struct scatterlist sg[CARM_MAX_REQ_SG];
|
struct scatterlist sg[CARM_MAX_REQ_SG];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -291,9 +287,6 @@ struct carm_host {
|
||||||
unsigned int wait_q_cons;
|
unsigned int wait_q_cons;
|
||||||
struct request_queue *wait_q[CARM_MAX_WAIT_Q];
|
struct request_queue *wait_q[CARM_MAX_WAIT_Q];
|
||||||
|
|
||||||
unsigned int n_msgs;
|
|
||||||
u64 msg_alloc;
|
|
||||||
struct carm_request req[CARM_MAX_REQ];
|
|
||||||
void *msg_base;
|
void *msg_base;
|
||||||
dma_addr_t msg_dma;
|
dma_addr_t msg_dma;
|
||||||
|
|
||||||
|
@ -478,10 +471,10 @@ static inline dma_addr_t carm_ref_msg_dma(struct carm_host *host,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int carm_send_msg(struct carm_host *host,
|
static int carm_send_msg(struct carm_host *host,
|
||||||
struct carm_request *crq)
|
struct carm_request *crq, unsigned tag)
|
||||||
{
|
{
|
||||||
void __iomem *mmio = host->mmio;
|
void __iomem *mmio = host->mmio;
|
||||||
u32 msg = (u32) carm_ref_msg_dma(host, crq->tag);
|
u32 msg = (u32) carm_ref_msg_dma(host, tag);
|
||||||
u32 cm_bucket = crq->msg_bucket;
|
u32 cm_bucket = crq->msg_bucket;
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
@ -506,99 +499,24 @@ static int carm_send_msg(struct carm_host *host,
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct carm_request *carm_get_request(struct carm_host *host)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
/* obey global hardware limit on S/G entries */
|
|
||||||
if (host->hw_sg_used >= (CARM_MAX_HOST_SG - CARM_MAX_REQ_SG))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
for (i = 0; i < max_queue; i++)
|
|
||||||
if ((host->msg_alloc & (1ULL << i)) == 0) {
|
|
||||||
struct carm_request *crq = &host->req[i];
|
|
||||||
crq->port = NULL;
|
|
||||||
crq->n_elem = 0;
|
|
||||||
|
|
||||||
host->msg_alloc |= (1ULL << i);
|
|
||||||
host->n_msgs++;
|
|
||||||
|
|
||||||
assert(host->n_msgs <= CARM_MAX_REQ);
|
|
||||||
sg_init_table(crq->sg, CARM_MAX_REQ_SG);
|
|
||||||
return crq;
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINTK("no request available, returning NULL\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int carm_put_request(struct carm_host *host, struct carm_request *crq)
|
|
||||||
{
|
|
||||||
assert(crq->tag < max_queue);
|
|
||||||
|
|
||||||
if (unlikely((host->msg_alloc & (1ULL << crq->tag)) == 0))
|
|
||||||
return -EINVAL; /* tried to clear a tag that was not active */
|
|
||||||
|
|
||||||
assert(host->hw_sg_used >= crq->n_elem);
|
|
||||||
|
|
||||||
host->msg_alloc &= ~(1ULL << crq->tag);
|
|
||||||
host->hw_sg_used -= crq->n_elem;
|
|
||||||
host->n_msgs--;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct carm_request *carm_get_special(struct carm_host *host)
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
struct carm_request *crq = NULL;
|
|
||||||
struct request *rq;
|
|
||||||
int tries = 5000;
|
|
||||||
|
|
||||||
while (tries-- > 0) {
|
|
||||||
spin_lock_irqsave(&host->lock, flags);
|
|
||||||
crq = carm_get_request(host);
|
|
||||||
spin_unlock_irqrestore(&host->lock, flags);
|
|
||||||
|
|
||||||
if (crq)
|
|
||||||
break;
|
|
||||||
msleep(10);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!crq)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
rq = blk_get_request(host->oob_q, REQ_OP_DRV_OUT, 0);
|
|
||||||
if (IS_ERR(rq)) {
|
|
||||||
spin_lock_irqsave(&host->lock, flags);
|
|
||||||
carm_put_request(host, crq);
|
|
||||||
spin_unlock_irqrestore(&host->lock, flags);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
crq->rq = rq;
|
|
||||||
return crq;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int carm_array_info (struct carm_host *host, unsigned int array_idx)
|
static int carm_array_info (struct carm_host *host, unsigned int array_idx)
|
||||||
{
|
{
|
||||||
struct carm_msg_ioctl *ioc;
|
struct carm_msg_ioctl *ioc;
|
||||||
unsigned int idx;
|
|
||||||
u32 msg_data;
|
u32 msg_data;
|
||||||
dma_addr_t msg_dma;
|
dma_addr_t msg_dma;
|
||||||
struct carm_request *crq;
|
struct carm_request *crq;
|
||||||
|
struct request *rq;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
crq = carm_get_special(host);
|
rq = blk_mq_alloc_request(host->oob_q, REQ_OP_DRV_OUT, 0);
|
||||||
if (!crq) {
|
if (IS_ERR(rq)) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
crq = blk_mq_rq_to_pdu(rq);
|
||||||
|
|
||||||
idx = crq->tag;
|
ioc = carm_ref_msg(host, rq->tag);
|
||||||
|
msg_dma = carm_ref_msg_dma(host, rq->tag);
|
||||||
ioc = carm_ref_msg(host, idx);
|
|
||||||
msg_dma = carm_ref_msg_dma(host, idx);
|
|
||||||
msg_data = (u32) (msg_dma + sizeof(struct carm_array_info));
|
msg_data = (u32) (msg_dma + sizeof(struct carm_array_info));
|
||||||
|
|
||||||
crq->msg_type = CARM_MSG_ARRAY;
|
crq->msg_type = CARM_MSG_ARRAY;
|
||||||
|
@ -612,7 +530,7 @@ static int carm_array_info (struct carm_host *host, unsigned int array_idx)
|
||||||
ioc->type = CARM_MSG_ARRAY;
|
ioc->type = CARM_MSG_ARRAY;
|
||||||
ioc->subtype = CARM_ARRAY_INFO;
|
ioc->subtype = CARM_ARRAY_INFO;
|
||||||
ioc->array_id = (u8) array_idx;
|
ioc->array_id = (u8) array_idx;
|
||||||
ioc->handle = cpu_to_le32(TAG_ENCODE(idx));
|
ioc->handle = cpu_to_le32(TAG_ENCODE(rq->tag));
|
||||||
ioc->data_addr = cpu_to_le32(msg_data);
|
ioc->data_addr = cpu_to_le32(msg_data);
|
||||||
|
|
||||||
spin_lock_irq(&host->lock);
|
spin_lock_irq(&host->lock);
|
||||||
|
@ -620,9 +538,8 @@ static int carm_array_info (struct carm_host *host, unsigned int array_idx)
|
||||||
host->state == HST_DEV_SCAN);
|
host->state == HST_DEV_SCAN);
|
||||||
spin_unlock_irq(&host->lock);
|
spin_unlock_irq(&host->lock);
|
||||||
|
|
||||||
DPRINTK("blk_execute_rq_nowait, tag == %u\n", idx);
|
DPRINTK("blk_execute_rq_nowait, tag == %u\n", rq->tag);
|
||||||
crq->rq->special = crq;
|
blk_execute_rq_nowait(host->oob_q, NULL, rq, true, NULL);
|
||||||
blk_execute_rq_nowait(host->oob_q, NULL, crq->rq, true, NULL);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -637,21 +554,21 @@ typedef unsigned int (*carm_sspc_t)(struct carm_host *, unsigned int, void *);
|
||||||
|
|
||||||
static int carm_send_special (struct carm_host *host, carm_sspc_t func)
|
static int carm_send_special (struct carm_host *host, carm_sspc_t func)
|
||||||
{
|
{
|
||||||
|
struct request *rq;
|
||||||
struct carm_request *crq;
|
struct carm_request *crq;
|
||||||
struct carm_msg_ioctl *ioc;
|
struct carm_msg_ioctl *ioc;
|
||||||
void *mem;
|
void *mem;
|
||||||
unsigned int idx, msg_size;
|
unsigned int msg_size;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
crq = carm_get_special(host);
|
rq = blk_mq_alloc_request(host->oob_q, REQ_OP_DRV_OUT, 0);
|
||||||
if (!crq)
|
if (IS_ERR(rq))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
crq = blk_mq_rq_to_pdu(rq);
|
||||||
|
|
||||||
idx = crq->tag;
|
mem = carm_ref_msg(host, rq->tag);
|
||||||
|
|
||||||
mem = carm_ref_msg(host, idx);
|
msg_size = func(host, rq->tag, mem);
|
||||||
|
|
||||||
msg_size = func(host, idx, mem);
|
|
||||||
|
|
||||||
ioc = mem;
|
ioc = mem;
|
||||||
crq->msg_type = ioc->type;
|
crq->msg_type = ioc->type;
|
||||||
|
@ -660,9 +577,8 @@ static int carm_send_special (struct carm_host *host, carm_sspc_t func)
|
||||||
BUG_ON(rc < 0);
|
BUG_ON(rc < 0);
|
||||||
crq->msg_bucket = (u32) rc;
|
crq->msg_bucket = (u32) rc;
|
||||||
|
|
||||||
DPRINTK("blk_execute_rq_nowait, tag == %u\n", idx);
|
DPRINTK("blk_execute_rq_nowait, tag == %u\n", rq->tag);
|
||||||
crq->rq->special = crq;
|
blk_execute_rq_nowait(host->oob_q, NULL, rq, true, NULL);
|
||||||
blk_execute_rq_nowait(host->oob_q, NULL, crq->rq, true, NULL);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -744,19 +660,6 @@ static unsigned int carm_fill_get_fw_ver(struct carm_host *host,
|
||||||
sizeof(struct carm_fw_ver);
|
sizeof(struct carm_fw_ver);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void carm_end_request_queued(struct carm_host *host,
|
|
||||||
struct carm_request *crq,
|
|
||||||
blk_status_t error)
|
|
||||||
{
|
|
||||||
struct request *req = crq->rq;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
blk_mq_end_request(req, error);
|
|
||||||
|
|
||||||
rc = carm_put_request(host, crq);
|
|
||||||
assert(rc == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void carm_push_q (struct carm_host *host, struct request_queue *q)
|
static inline void carm_push_q (struct carm_host *host, struct request_queue *q)
|
||||||
{
|
{
|
||||||
unsigned int idx = host->wait_q_prod % CARM_MAX_WAIT_Q;
|
unsigned int idx = host->wait_q_prod % CARM_MAX_WAIT_Q;
|
||||||
|
@ -791,101 +694,50 @@ static inline void carm_round_robin(struct carm_host *host)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void carm_end_rq(struct carm_host *host, struct carm_request *crq,
|
static inline enum dma_data_direction carm_rq_dir(struct request *rq)
|
||||||
blk_status_t error)
|
|
||||||
{
|
{
|
||||||
carm_end_request_queued(host, crq, error);
|
return op_is_write(req_op(rq)) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
|
||||||
if (max_queue == 1)
|
|
||||||
carm_round_robin(host);
|
|
||||||
else if ((host->n_msgs <= CARM_MSG_LOW_WATER) &&
|
|
||||||
(host->hw_sg_used <= CARM_SG_LOW_WATER)) {
|
|
||||||
carm_round_robin(host);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static blk_status_t carm_oob_queue_rq(struct blk_mq_hw_ctx *hctx,
|
|
||||||
const struct blk_mq_queue_data *bd)
|
|
||||||
{
|
|
||||||
struct request_queue *q = hctx->queue;
|
|
||||||
struct carm_host *host = q->queuedata;
|
|
||||||
struct carm_request *crq;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
blk_mq_start_request(bd->rq);
|
|
||||||
|
|
||||||
spin_lock_irq(&host->lock);
|
|
||||||
|
|
||||||
crq = bd->rq->special;
|
|
||||||
assert(crq != NULL);
|
|
||||||
assert(crq->rq == bd->rq);
|
|
||||||
|
|
||||||
crq->n_elem = 0;
|
|
||||||
|
|
||||||
DPRINTK("send req\n");
|
|
||||||
rc = carm_send_msg(host, crq);
|
|
||||||
if (rc) {
|
|
||||||
carm_push_q(host, q);
|
|
||||||
spin_unlock_irq(&host->lock);
|
|
||||||
return BLK_STS_DEV_RESOURCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_unlock_irq(&host->lock);
|
|
||||||
return BLK_STS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static blk_status_t carm_queue_rq(struct blk_mq_hw_ctx *hctx,
|
static blk_status_t carm_queue_rq(struct blk_mq_hw_ctx *hctx,
|
||||||
const struct blk_mq_queue_data *bd)
|
const struct blk_mq_queue_data *bd)
|
||||||
{
|
{
|
||||||
struct request_queue *q = hctx->queue;
|
struct request_queue *q = hctx->queue;
|
||||||
|
struct request *rq = bd->rq;
|
||||||
struct carm_port *port = q->queuedata;
|
struct carm_port *port = q->queuedata;
|
||||||
struct carm_host *host = port->host;
|
struct carm_host *host = port->host;
|
||||||
|
struct carm_request *crq = blk_mq_rq_to_pdu(rq);
|
||||||
struct carm_msg_rw *msg;
|
struct carm_msg_rw *msg;
|
||||||
struct carm_request *crq;
|
|
||||||
struct request *rq = bd->rq;
|
|
||||||
struct scatterlist *sg;
|
struct scatterlist *sg;
|
||||||
int writing = 0, pci_dir, i, n_elem, rc;
|
int i, n_elem = 0, rc;
|
||||||
u32 tmp;
|
|
||||||
unsigned int msg_size;
|
unsigned int msg_size;
|
||||||
|
u32 tmp;
|
||||||
|
|
||||||
|
crq->n_elem = 0;
|
||||||
|
sg_init_table(crq->sg, CARM_MAX_REQ_SG);
|
||||||
|
|
||||||
blk_mq_start_request(rq);
|
blk_mq_start_request(rq);
|
||||||
|
|
||||||
spin_lock_irq(&host->lock);
|
spin_lock_irq(&host->lock);
|
||||||
|
if (req_op(rq) == REQ_OP_DRV_OUT)
|
||||||
crq = carm_get_request(host);
|
goto send_msg;
|
||||||
if (!crq) {
|
|
||||||
carm_push_q(host, q);
|
|
||||||
spin_unlock_irq(&host->lock);
|
|
||||||
return BLK_STS_DEV_RESOURCE;
|
|
||||||
}
|
|
||||||
crq->rq = rq;
|
|
||||||
|
|
||||||
if (rq_data_dir(rq) == WRITE) {
|
|
||||||
writing = 1;
|
|
||||||
pci_dir = DMA_TO_DEVICE;
|
|
||||||
} else {
|
|
||||||
pci_dir = DMA_FROM_DEVICE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get scatterlist from block layer */
|
/* get scatterlist from block layer */
|
||||||
sg = &crq->sg[0];
|
sg = &crq->sg[0];
|
||||||
n_elem = blk_rq_map_sg(q, rq, sg);
|
n_elem = blk_rq_map_sg(q, rq, sg);
|
||||||
if (n_elem <= 0) {
|
if (n_elem <= 0)
|
||||||
/* request with no s/g entries? */
|
goto out_ioerr;
|
||||||
carm_end_rq(host, crq, BLK_STS_IOERR);
|
|
||||||
spin_unlock_irq(&host->lock);
|
|
||||||
return BLK_STS_IOERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* map scatterlist to PCI bus addresses */
|
/* map scatterlist to PCI bus addresses */
|
||||||
n_elem = dma_map_sg(&host->pdev->dev, sg, n_elem, pci_dir);
|
n_elem = dma_map_sg(&host->pdev->dev, sg, n_elem, carm_rq_dir(rq));
|
||||||
if (n_elem <= 0) {
|
if (n_elem <= 0)
|
||||||
/* request with no s/g entries? */
|
goto out_ioerr;
|
||||||
carm_end_rq(host, crq, BLK_STS_IOERR);
|
|
||||||
spin_unlock_irq(&host->lock);
|
/* obey global hardware limit on S/G entries */
|
||||||
return BLK_STS_IOERR;
|
if (host->hw_sg_used >= CARM_MAX_HOST_SG - n_elem)
|
||||||
}
|
goto out_resource;
|
||||||
|
|
||||||
crq->n_elem = n_elem;
|
crq->n_elem = n_elem;
|
||||||
crq->port = port;
|
|
||||||
host->hw_sg_used += n_elem;
|
host->hw_sg_used += n_elem;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -893,9 +745,9 @@ static blk_status_t carm_queue_rq(struct blk_mq_hw_ctx *hctx,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
VPRINTK("build msg\n");
|
VPRINTK("build msg\n");
|
||||||
msg = (struct carm_msg_rw *) carm_ref_msg(host, crq->tag);
|
msg = (struct carm_msg_rw *) carm_ref_msg(host, rq->tag);
|
||||||
|
|
||||||
if (writing) {
|
if (rq_data_dir(rq) == WRITE) {
|
||||||
msg->type = CARM_MSG_WRITE;
|
msg->type = CARM_MSG_WRITE;
|
||||||
crq->msg_type = CARM_MSG_WRITE;
|
crq->msg_type = CARM_MSG_WRITE;
|
||||||
} else {
|
} else {
|
||||||
|
@ -906,7 +758,7 @@ static blk_status_t carm_queue_rq(struct blk_mq_hw_ctx *hctx,
|
||||||
msg->id = port->port_no;
|
msg->id = port->port_no;
|
||||||
msg->sg_count = n_elem;
|
msg->sg_count = n_elem;
|
||||||
msg->sg_type = SGT_32BIT;
|
msg->sg_type = SGT_32BIT;
|
||||||
msg->handle = cpu_to_le32(TAG_ENCODE(crq->tag));
|
msg->handle = cpu_to_le32(TAG_ENCODE(rq->tag));
|
||||||
msg->lba = cpu_to_le32(blk_rq_pos(rq) & 0xffffffff);
|
msg->lba = cpu_to_le32(blk_rq_pos(rq) & 0xffffffff);
|
||||||
tmp = (blk_rq_pos(rq) >> 16) >> 16;
|
tmp = (blk_rq_pos(rq) >> 16) >> 16;
|
||||||
msg->lba_high = cpu_to_le16( (u16) tmp );
|
msg->lba_high = cpu_to_le16( (u16) tmp );
|
||||||
|
@ -923,22 +775,28 @@ static blk_status_t carm_queue_rq(struct blk_mq_hw_ctx *hctx,
|
||||||
rc = carm_lookup_bucket(msg_size);
|
rc = carm_lookup_bucket(msg_size);
|
||||||
BUG_ON(rc < 0);
|
BUG_ON(rc < 0);
|
||||||
crq->msg_bucket = (u32) rc;
|
crq->msg_bucket = (u32) rc;
|
||||||
|
send_msg:
|
||||||
/*
|
/*
|
||||||
* queue read/write message to hardware
|
* queue read/write message to hardware
|
||||||
*/
|
*/
|
||||||
|
VPRINTK("send msg, tag == %u\n", rq->tag);
|
||||||
VPRINTK("send msg, tag == %u\n", crq->tag);
|
rc = carm_send_msg(host, crq, rq->tag);
|
||||||
rc = carm_send_msg(host, crq);
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
carm_put_request(host, crq);
|
host->hw_sg_used -= n_elem;
|
||||||
carm_push_q(host, q);
|
goto out_resource;
|
||||||
spin_unlock_irq(&host->lock);
|
|
||||||
return BLK_STS_DEV_RESOURCE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irq(&host->lock);
|
spin_unlock_irq(&host->lock);
|
||||||
return BLK_STS_OK;
|
return BLK_STS_OK;
|
||||||
|
out_resource:
|
||||||
|
dma_unmap_sg(&host->pdev->dev, &crq->sg[0], n_elem, carm_rq_dir(rq));
|
||||||
|
carm_push_q(host, q);
|
||||||
|
spin_unlock_irq(&host->lock);
|
||||||
|
return BLK_STS_DEV_RESOURCE;
|
||||||
|
out_ioerr:
|
||||||
|
carm_round_robin(host);
|
||||||
|
spin_unlock_irq(&host->lock);
|
||||||
|
return BLK_STS_IOERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void carm_handle_array_info(struct carm_host *host,
|
static void carm_handle_array_info(struct carm_host *host,
|
||||||
|
@ -954,8 +812,6 @@ static void carm_handle_array_info(struct carm_host *host,
|
||||||
|
|
||||||
DPRINTK("ENTER\n");
|
DPRINTK("ENTER\n");
|
||||||
|
|
||||||
carm_end_rq(host, crq, error);
|
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
goto out;
|
goto out;
|
||||||
if (le32_to_cpu(desc->array_status) & ARRAY_NO_EXIST)
|
if (le32_to_cpu(desc->array_status) & ARRAY_NO_EXIST)
|
||||||
|
@ -1011,8 +867,6 @@ static void carm_handle_scan_chan(struct carm_host *host,
|
||||||
|
|
||||||
DPRINTK("ENTER\n");
|
DPRINTK("ENTER\n");
|
||||||
|
|
||||||
carm_end_rq(host, crq, error);
|
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
new_state = HST_ERROR;
|
new_state = HST_ERROR;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -1040,8 +894,6 @@ static void carm_handle_generic(struct carm_host *host,
|
||||||
{
|
{
|
||||||
DPRINTK("ENTER\n");
|
DPRINTK("ENTER\n");
|
||||||
|
|
||||||
carm_end_rq(host, crq, error);
|
|
||||||
|
|
||||||
assert(host->state == cur_state);
|
assert(host->state == cur_state);
|
||||||
if (error)
|
if (error)
|
||||||
host->state = HST_ERROR;
|
host->state = HST_ERROR;
|
||||||
|
@ -1050,28 +902,12 @@ static void carm_handle_generic(struct carm_host *host,
|
||||||
schedule_work(&host->fsm_task);
|
schedule_work(&host->fsm_task);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void carm_handle_rw(struct carm_host *host,
|
|
||||||
struct carm_request *crq, blk_status_t error)
|
|
||||||
{
|
|
||||||
int pci_dir;
|
|
||||||
|
|
||||||
VPRINTK("ENTER\n");
|
|
||||||
|
|
||||||
if (rq_data_dir(crq->rq) == WRITE)
|
|
||||||
pci_dir = DMA_TO_DEVICE;
|
|
||||||
else
|
|
||||||
pci_dir = DMA_FROM_DEVICE;
|
|
||||||
|
|
||||||
dma_unmap_sg(&host->pdev->dev, &crq->sg[0], crq->n_elem, pci_dir);
|
|
||||||
|
|
||||||
carm_end_rq(host, crq, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void carm_handle_resp(struct carm_host *host,
|
static inline void carm_handle_resp(struct carm_host *host,
|
||||||
__le32 ret_handle_le, u32 status)
|
__le32 ret_handle_le, u32 status)
|
||||||
{
|
{
|
||||||
u32 handle = le32_to_cpu(ret_handle_le);
|
u32 handle = le32_to_cpu(ret_handle_le);
|
||||||
unsigned int msg_idx;
|
unsigned int msg_idx;
|
||||||
|
struct request *rq;
|
||||||
struct carm_request *crq;
|
struct carm_request *crq;
|
||||||
blk_status_t error = (status == RMSG_OK) ? 0 : BLK_STS_IOERR;
|
blk_status_t error = (status == RMSG_OK) ? 0 : BLK_STS_IOERR;
|
||||||
u8 *mem;
|
u8 *mem;
|
||||||
|
@ -1087,13 +923,15 @@ static inline void carm_handle_resp(struct carm_host *host,
|
||||||
msg_idx = TAG_DECODE(handle);
|
msg_idx = TAG_DECODE(handle);
|
||||||
VPRINTK("tag == %u\n", msg_idx);
|
VPRINTK("tag == %u\n", msg_idx);
|
||||||
|
|
||||||
crq = &host->req[msg_idx];
|
rq = blk_mq_tag_to_rq(host->tag_set.tags[0], msg_idx);
|
||||||
|
crq = blk_mq_rq_to_pdu(rq);
|
||||||
|
|
||||||
/* fast path */
|
/* fast path */
|
||||||
if (likely(crq->msg_type == CARM_MSG_READ ||
|
if (likely(crq->msg_type == CARM_MSG_READ ||
|
||||||
crq->msg_type == CARM_MSG_WRITE)) {
|
crq->msg_type == CARM_MSG_WRITE)) {
|
||||||
carm_handle_rw(host, crq, error);
|
dma_unmap_sg(&host->pdev->dev, &crq->sg[0], crq->n_elem,
|
||||||
return;
|
carm_rq_dir(rq));
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
mem = carm_ref_msg(host, msg_idx);
|
mem = carm_ref_msg(host, msg_idx);
|
||||||
|
@ -1103,7 +941,7 @@ static inline void carm_handle_resp(struct carm_host *host,
|
||||||
switch (crq->msg_subtype) {
|
switch (crq->msg_subtype) {
|
||||||
case CARM_IOC_SCAN_CHAN:
|
case CARM_IOC_SCAN_CHAN:
|
||||||
carm_handle_scan_chan(host, crq, mem, error);
|
carm_handle_scan_chan(host, crq, mem, error);
|
||||||
break;
|
goto done;
|
||||||
default:
|
default:
|
||||||
/* unknown / invalid response */
|
/* unknown / invalid response */
|
||||||
goto err_out;
|
goto err_out;
|
||||||
|
@ -1116,11 +954,11 @@ static inline void carm_handle_resp(struct carm_host *host,
|
||||||
case MISC_ALLOC_MEM:
|
case MISC_ALLOC_MEM:
|
||||||
carm_handle_generic(host, crq, error,
|
carm_handle_generic(host, crq, error,
|
||||||
HST_ALLOC_BUF, HST_SYNC_TIME);
|
HST_ALLOC_BUF, HST_SYNC_TIME);
|
||||||
break;
|
goto done;
|
||||||
case MISC_SET_TIME:
|
case MISC_SET_TIME:
|
||||||
carm_handle_generic(host, crq, error,
|
carm_handle_generic(host, crq, error,
|
||||||
HST_SYNC_TIME, HST_GET_FW_VER);
|
HST_SYNC_TIME, HST_GET_FW_VER);
|
||||||
break;
|
goto done;
|
||||||
case MISC_GET_FW_VER: {
|
case MISC_GET_FW_VER: {
|
||||||
struct carm_fw_ver *ver = (struct carm_fw_ver *)
|
struct carm_fw_ver *ver = (struct carm_fw_ver *)
|
||||||
(mem + sizeof(struct carm_msg_get_fw_ver));
|
(mem + sizeof(struct carm_msg_get_fw_ver));
|
||||||
|
@ -1130,7 +968,7 @@ static inline void carm_handle_resp(struct carm_host *host,
|
||||||
}
|
}
|
||||||
carm_handle_generic(host, crq, error,
|
carm_handle_generic(host, crq, error,
|
||||||
HST_GET_FW_VER, HST_PORT_SCAN);
|
HST_GET_FW_VER, HST_PORT_SCAN);
|
||||||
break;
|
goto done;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
/* unknown / invalid response */
|
/* unknown / invalid response */
|
||||||
|
@ -1161,7 +999,13 @@ static inline void carm_handle_resp(struct carm_host *host,
|
||||||
err_out:
|
err_out:
|
||||||
printk(KERN_WARNING DRV_NAME "(%s): BUG: unhandled message type %d/%d\n",
|
printk(KERN_WARNING DRV_NAME "(%s): BUG: unhandled message type %d/%d\n",
|
||||||
pci_name(host->pdev), crq->msg_type, crq->msg_subtype);
|
pci_name(host->pdev), crq->msg_type, crq->msg_subtype);
|
||||||
carm_end_rq(host, crq, BLK_STS_IOERR);
|
error = BLK_STS_IOERR;
|
||||||
|
done:
|
||||||
|
host->hw_sg_used -= crq->n_elem;
|
||||||
|
blk_mq_end_request(blk_mq_rq_from_pdu(crq), error);
|
||||||
|
|
||||||
|
if (host->hw_sg_used <= CARM_SG_LOW_WATER)
|
||||||
|
carm_round_robin(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void carm_handle_responses(struct carm_host *host)
|
static inline void carm_handle_responses(struct carm_host *host)
|
||||||
|
@ -1491,10 +1335,6 @@ static int carm_init_host(struct carm_host *host)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct blk_mq_ops carm_oob_mq_ops = {
|
|
||||||
.queue_rq = carm_oob_queue_rq,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct blk_mq_ops carm_mq_ops = {
|
static const struct blk_mq_ops carm_mq_ops = {
|
||||||
.queue_rq = carm_queue_rq,
|
.queue_rq = carm_queue_rq,
|
||||||
};
|
};
|
||||||
|
@ -1520,15 +1360,15 @@ static int carm_init_disk(struct carm_host *host, unsigned int port_no)
|
||||||
disk->fops = &carm_bd_ops;
|
disk->fops = &carm_bd_ops;
|
||||||
disk->private_data = port;
|
disk->private_data = port;
|
||||||
|
|
||||||
q = blk_mq_init_sq_queue(&port->tag_set, &carm_mq_ops,
|
q = blk_mq_init_queue(&host->tag_set);
|
||||||
max_queue, BLK_MQ_F_SHOULD_MERGE);
|
|
||||||
if (IS_ERR(q))
|
if (IS_ERR(q))
|
||||||
return PTR_ERR(q);
|
return PTR_ERR(q);
|
||||||
disk->queue = q;
|
|
||||||
blk_queue_max_segments(q, CARM_MAX_REQ_SG);
|
blk_queue_max_segments(q, CARM_MAX_REQ_SG);
|
||||||
blk_queue_segment_boundary(q, CARM_SG_BOUNDARY);
|
blk_queue_segment_boundary(q, CARM_SG_BOUNDARY);
|
||||||
|
|
||||||
q->queuedata = port;
|
q->queuedata = port;
|
||||||
|
disk->queue = q;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1542,10 +1382,8 @@ static void carm_free_disk(struct carm_host *host, unsigned int port_no)
|
||||||
|
|
||||||
if (disk->flags & GENHD_FL_UP)
|
if (disk->flags & GENHD_FL_UP)
|
||||||
del_gendisk(disk);
|
del_gendisk(disk);
|
||||||
if (disk->queue) {
|
if (disk->queue)
|
||||||
blk_mq_free_tag_set(&port->tag_set);
|
|
||||||
blk_cleanup_queue(disk->queue);
|
blk_cleanup_queue(disk->queue);
|
||||||
}
|
|
||||||
put_disk(disk);
|
put_disk(disk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1602,9 +1440,6 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||||
INIT_WORK(&host->fsm_task, carm_fsm_task);
|
INIT_WORK(&host->fsm_task, carm_fsm_task);
|
||||||
init_completion(&host->probe_comp);
|
init_completion(&host->probe_comp);
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(host->req); i++)
|
|
||||||
host->req[i].tag = i;
|
|
||||||
|
|
||||||
host->mmio = ioremap(pci_resource_start(pdev, 0),
|
host->mmio = ioremap(pci_resource_start(pdev, 0),
|
||||||
pci_resource_len(pdev, 0));
|
pci_resource_len(pdev, 0));
|
||||||
if (!host->mmio) {
|
if (!host->mmio) {
|
||||||
|
@ -1621,14 +1456,26 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||||
goto err_out_iounmap;
|
goto err_out_iounmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
q = blk_mq_init_sq_queue(&host->tag_set, &carm_oob_mq_ops, 1,
|
memset(&host->tag_set, 0, sizeof(host->tag_set));
|
||||||
BLK_MQ_F_NO_SCHED);
|
host->tag_set.ops = &carm_mq_ops;
|
||||||
|
host->tag_set.cmd_size = sizeof(struct carm_request);
|
||||||
|
host->tag_set.nr_hw_queues = 1;
|
||||||
|
host->tag_set.nr_maps = 1;
|
||||||
|
host->tag_set.queue_depth = max_queue;
|
||||||
|
host->tag_set.numa_node = NUMA_NO_NODE;
|
||||||
|
host->tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
|
||||||
|
|
||||||
|
rc = blk_mq_alloc_tag_set(&host->tag_set);
|
||||||
|
if (rc)
|
||||||
|
goto err_out_dma_free;
|
||||||
|
|
||||||
|
q = blk_mq_init_queue(&host->tag_set);
|
||||||
if (IS_ERR(q)) {
|
if (IS_ERR(q)) {
|
||||||
printk(KERN_ERR DRV_NAME "(%s): OOB queue alloc failure\n",
|
|
||||||
pci_name(pdev));
|
|
||||||
rc = PTR_ERR(q);
|
rc = PTR_ERR(q);
|
||||||
|
blk_mq_free_tag_set(&host->tag_set);
|
||||||
goto err_out_dma_free;
|
goto err_out_dma_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
host->oob_q = q;
|
host->oob_q = q;
|
||||||
q->queuedata = host;
|
q->queuedata = host;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue