Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 264676
b: refs/heads/master
c: 02b1a74
h: refs/heads/master
v: v3
  • Loading branch information
Christoph Hellwig authored and Nicholas Bellinger committed Oct 24, 2011
1 parent 0886a84 commit 03a5a37
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 175 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: dbbf3e94c2b26988d3c41af63e50189e9133eb28
refs/heads/master: 02b1a7463420e1cebe86c6755c44d3bd9489829e
265 changes: 92 additions & 173 deletions trunk/drivers/target/target_core_pscsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -776,95 +776,6 @@ pscsi_alloc_task(unsigned char *cdb)
return &pt->pscsi_task;
}

static inline void pscsi_blk_init_request(
struct se_task *task,
struct pscsi_plugin_task *pt,
struct request *req,
int bidi_read)
{
/*
* Defined as "scsi command" in include/linux/blkdev.h.
*/
req->cmd_type = REQ_TYPE_BLOCK_PC;
/*
* For the extra BIDI-COMMAND READ struct request we do not
* need to setup the remaining structure members
*/
if (bidi_read)
return;
/*
* Setup the done function pointer for struct request,
* also set the end_io_data pointer.to struct se_task.
*/
req->end_io = pscsi_req_done;
req->end_io_data = task;
/*
* Load the referenced struct se_task's SCSI CDB into
* include/linux/blkdev.h:struct request->cmd
*/
req->cmd_len = scsi_command_size(pt->pscsi_cdb);
req->cmd = &pt->pscsi_cdb[0];
/*
* Setup pointer for outgoing sense data.
*/
req->sense = &pt->pscsi_sense[0];
req->sense_len = 0;
}

/*
* Used for pSCSI data payloads for all *NON* SCF_SCSI_DATA_SG_IO_CDB
*/
static int pscsi_blk_get_request(struct se_task *task)
{
struct pscsi_plugin_task *pt = PSCSI_TASK(task);
struct pscsi_dev_virt *pdv = task->se_dev->dev_ptr;

pt->pscsi_req = blk_get_request(pdv->pdv_sd->request_queue,
(task->task_data_direction == DMA_TO_DEVICE),
GFP_KERNEL);
if (!pt->pscsi_req || IS_ERR(pt->pscsi_req)) {
pr_err("PSCSI: blk_get_request() failed: %ld\n",
IS_ERR(pt->pscsi_req));
return PYX_TRANSPORT_LU_COMM_FAILURE;
}
/*
* Setup the newly allocated struct request for REQ_TYPE_BLOCK_PC,
* and setup rq callback, CDB and sense.
*/
pscsi_blk_init_request(task, pt, pt->pscsi_req, 0);
return 0;
}

/* pscsi_do_task(): (Part of se_subsystem_api_t template)
*
*
*/
static int pscsi_do_task(struct se_task *task)
{
struct pscsi_plugin_task *pt = PSCSI_TASK(task);
struct pscsi_dev_virt *pdv = task->se_dev->dev_ptr;
/*
* Set the struct request->timeout value based on peripheral
* device type from SCSI.
*/
if (pdv->pdv_sd->type == TYPE_DISK)
pt->pscsi_req->timeout = PS_TIMEOUT_DISK;
else
pt->pscsi_req->timeout = PS_TIMEOUT_OTHER;

pt->pscsi_req->retries = PS_RETRY;
/*
* Queue the struct request into the struct scsi_device->request_queue.
* Also check for HEAD_OF_QUEUE SAM TASK attr from received se_cmd
* descriptor
*/
blk_execute_rq_nowait(pdv->pdv_sd->request_queue, NULL, pt->pscsi_req,
(task->task_se_cmd->sam_task_attr == MSG_HEAD_TAG),
pscsi_req_done);

return PYX_TRANSPORT_SENT_TO_TRANSPORT;
}

static void pscsi_free_task(struct se_task *task)
{
struct pscsi_plugin_task *pt = PSCSI_TASK(task);
Expand Down Expand Up @@ -1048,15 +959,12 @@ static inline struct bio *pscsi_get_bio(int sg_num)
return bio;
}

static int __pscsi_map_SG(
struct se_task *task,
struct scatterlist *task_sg,
u32 task_sg_num,
int bidi_read)
static int pscsi_map_sg(struct se_task *task, struct scatterlist *task_sg,
struct bio **hbio)
{
struct pscsi_plugin_task *pt = PSCSI_TASK(task);
struct pscsi_dev_virt *pdv = task->se_dev->dev_ptr;
struct bio *bio = NULL, *hbio = NULL, *tbio = NULL;
u32 task_sg_num = task->task_sg_nents;
struct bio *bio = NULL, *tbio = NULL;
struct page *page;
struct scatterlist *sg;
u32 data_len = task->task_size, i, len, bytes, off;
Expand All @@ -1065,19 +973,8 @@ static int __pscsi_map_SG(
int nr_vecs = 0, rc, ret = PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES;
int rw = (task->task_data_direction == DMA_TO_DEVICE);

if (!task->task_size)
return 0;
/*
* For SCF_SCSI_DATA_SG_IO_CDB, Use fs/bio.c:bio_add_page() to setup
* the bio_vec maplist from task->task_sg ->
* struct scatterlist memory. The struct se_task->task_sg[] currently needs
* to be attached to struct bios for submission to Linux/SCSI using
* struct request to struct scsi_device->request_queue.
*
* Note that this will be changing post v2.6.28 as Target_Core_Mod/pSCSI
* is ported to upstream SCSI passthrough functionality that accepts
* struct scatterlist->page_link or struct page as a paraemeter.
*/
*hbio = NULL;

pr_debug("PSCSI: nr_pages: %d\n", nr_pages);

for_each_sg(task_sg, sg, task_sg_num, i) {
Expand Down Expand Up @@ -1114,8 +1011,8 @@ static int __pscsi_map_SG(
* bios need to be added to complete a given
* struct se_task
*/
if (!hbio)
hbio = tbio = bio;
if (!*hbio)
*hbio = tbio = bio;
else
tbio = tbio->bi_next = bio;
}
Expand Down Expand Up @@ -1151,83 +1048,109 @@ static int __pscsi_map_SG(
off = 0;
}
}
/*
* Setup the primary pt->pscsi_req used for non BIDI and BIDI-COMMAND
* primary SCSI WRITE poayload mapped for struct se_task->task_sg[]
*/
if (!bidi_read) {
/*
* Starting with v2.6.31, call blk_make_request() passing in *hbio to
* allocate the pSCSI task a struct request.
*/
pt->pscsi_req = blk_make_request(pdv->pdv_sd->request_queue,
hbio, GFP_KERNEL);
if (!pt->pscsi_req) {
pr_err("pSCSI: blk_make_request() failed\n");
goto fail;
}
/*
* Setup the newly allocated struct request for REQ_TYPE_BLOCK_PC,
* and setup rq callback, CDB and sense.
*/
pscsi_blk_init_request(task, pt, pt->pscsi_req, 0);

return task->task_sg_nents;
}
/*
* Setup the secondary pt->pscsi_req->next_rq used for the extra BIDI-COMMAND
* SCSI READ paylaod mapped for struct se_task->task_sg_bidi[]
*/
pt->pscsi_req->next_rq = blk_make_request(pdv->pdv_sd->request_queue,
hbio, GFP_KERNEL);
if (!pt->pscsi_req->next_rq) {
pr_err("pSCSI: blk_make_request() failed for BIDI\n");
goto fail;
}
pscsi_blk_init_request(task, pt, pt->pscsi_req->next_rq, 1);

return task->task_sg_nents;
fail:
while (hbio) {
bio = hbio;
hbio = hbio->bi_next;
while (*hbio) {
bio = *hbio;
*hbio = (*hbio)->bi_next;
bio->bi_next = NULL;
bio_endio(bio, 0);
bio_endio(bio, 0); /* XXX: should be error */
}
return ret;
}

/*
* pSCSI maps both ->map_control_SG() and ->map_data_SG() to a single call.
*/
static int pscsi_map_SG(struct se_task *task)
static int pscsi_do_task(struct se_task *task)
{
struct pscsi_dev_virt *pdv = task->se_dev->dev_ptr;
struct pscsi_plugin_task *pt = PSCSI_TASK(task);
struct request *req;
struct bio *hbio;
int ret;

/*
* Setup the main struct request for the task->task_sg[] payload
*/
if (task->task_se_cmd->se_cmd_flags & SCF_SCSI_NON_DATA_CDB) {
req = blk_get_request(pdv->pdv_sd->request_queue,
(task->task_data_direction == DMA_TO_DEVICE),
GFP_KERNEL);
if (!req || IS_ERR(req)) {
pr_err("PSCSI: blk_get_request() failed: %ld\n",
req ? IS_ERR(req) : -ENOMEM);
return PYX_TRANSPORT_LU_COMM_FAILURE;
}
} else {
BUG_ON(!task->task_size);

ret = __pscsi_map_SG(task, task->task_sg, task->task_sg_nents, 0);
if (ret >= 0 && task->task_sg_bidi) {
/*
* If present, set up the extra BIDI-COMMAND SCSI READ
* struct request and payload.
* Setup the main struct request for the task->task_sg[] payload
*/
ret = __pscsi_map_SG(task, task->task_sg_bidi,
task->task_sg_nents, 1);
ret = pscsi_map_sg(task, task->task_sg, &hbio);
if (ret < 0)
return PYX_TRANSPORT_LU_COMM_FAILURE;

req = blk_make_request(pdv->pdv_sd->request_queue, hbio,
GFP_KERNEL);
if (!req) {
pr_err("pSCSI: blk_make_request() failed\n");
goto fail;
}

if (task->task_sg_bidi) {
/*
* If present, set up the extra BIDI-COMMAND SCSI READ
* struct request and payload.
*/
ret = pscsi_map_sg(task, task->task_sg_bidi, &hbio);
if (ret < 0) {
/* XXX: free the main request? */
return PYX_TRANSPORT_LU_COMM_FAILURE;
}

/*
* Setup the secondary pt->pscsi_req->next_rq used for the extra
* BIDI READ payload.
*/
req->next_rq = blk_make_request(pdv->pdv_sd->request_queue,
hbio, GFP_KERNEL);
if (!req) {
pr_err("pSCSI: blk_make_request() failed for BIDI\n");
/* XXX: free the main request? */
goto fail;
}

req->next_rq->cmd_type = REQ_TYPE_BLOCK_PC;
}
}

if (ret < 0)
return PYX_TRANSPORT_LU_COMM_FAILURE;
return 0;
}
req->cmd_type = REQ_TYPE_BLOCK_PC;
req->end_io = pscsi_req_done;
req->end_io_data = task;
req->cmd_len = scsi_command_size(pt->pscsi_cdb);
req->cmd = &pt->pscsi_cdb[0];
req->sense = &pt->pscsi_sense[0];
req->sense_len = 0;
if (pdv->pdv_sd->type == TYPE_DISK)
req->timeout = PS_TIMEOUT_DISK;
else
req->timeout = PS_TIMEOUT_OTHER;
req->retries = PS_RETRY;

static int pscsi_CDB_none(struct se_task *task)
{
return pscsi_blk_get_request(task);
blk_execute_rq_nowait(pdv->pdv_sd->request_queue, NULL, req,
(task->task_se_cmd->sam_task_attr == MSG_HEAD_TAG),
pscsi_req_done);

return PYX_TRANSPORT_SENT_TO_TRANSPORT;

fail:
while (hbio) {
struct bio *bio = hbio;
hbio = hbio->bi_next;
bio->bi_next = NULL;
bio_endio(bio, 0); /* XXX: should be error */
}
return PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES;
}


/* pscsi_get_cdb():
*
*
Expand Down Expand Up @@ -1334,16 +1257,12 @@ static void pscsi_req_done(struct request *req, int uptodate)
__blk_put_request(req->q, req->next_rq);

__blk_put_request(req->q, req);
pt->pscsi_req = NULL;
}

static struct se_subsystem_api pscsi_template = {
.name = "pscsi",
.owner = THIS_MODULE,
.transport_type = TRANSPORT_PLUGIN_PHBA_PDEV,
.cdb_none = pscsi_CDB_none,
.map_control_SG = pscsi_map_SG,
.map_data_SG = pscsi_map_SG,
.attach_hba = pscsi_attach_hba,
.detach_hba = pscsi_detach_hba,
.pmode_enable_hba = pscsi_pmode_enable_hba,
Expand Down
1 change: 0 additions & 1 deletion trunk/drivers/target/target_core_pscsi.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ struct pscsi_plugin_task {
int pscsi_direction;
int pscsi_result;
u32 pscsi_resid;
struct request *pscsi_req;
unsigned char pscsi_cdb[0];
} ____cacheline_aligned;

Expand Down

0 comments on commit 03a5a37

Please sign in to comment.