Skip to content

Commit

Permalink
[SCSI] qla2xxx: Add I2C BSG interface.
Browse files Browse the repository at this point in the history
Add BSG interface to generically access I2C attached devices.

Signed-off-by: Joe Carnuccio <joe.carnuccio@qlogic.com>
Signed-off-by: Chad Dupuis <chad.dupuis@qlogic.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
  • Loading branch information
Joe Carnuccio authored and James Bottomley committed Sep 14, 2012
1 parent 650f528 commit 9ebb5d9
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 0 deletions.
96 changes: 96 additions & 0 deletions drivers/scsi/qla2xxx/qla_bsg.c
Original file line number Diff line number Diff line change
Expand Up @@ -1559,6 +1559,96 @@ qla2x00_write_fru_status(struct fc_bsg_job *bsg_job)
return 0;
}

static int
qla2x00_write_i2c(struct fc_bsg_job *bsg_job)
{
struct Scsi_Host *host = bsg_job->shost;
scsi_qla_host_t *vha = shost_priv(host);
struct qla_hw_data *ha = vha->hw;
int rval = 0;
uint8_t bsg[DMA_POOL_SIZE];
struct qla_i2c_access *i2c = (void *)bsg;
dma_addr_t sfp_dma;
uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
if (!sfp) {
bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
EXT_STATUS_NO_MEMORY;
goto done;
}

sg_copy_to_buffer(bsg_job->request_payload.sg_list,
bsg_job->request_payload.sg_cnt, i2c, sizeof(*i2c));

memcpy(sfp, i2c->buffer, i2c->length);
rval = qla2x00_write_sfp(vha, sfp_dma, sfp,
i2c->device, i2c->offset, i2c->length, i2c->option);

if (rval) {
bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
EXT_STATUS_MAILBOX;
goto dealloc;
}

bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = 0;

dealloc:
dma_pool_free(ha->s_dma_pool, sfp, sfp_dma);

done:
bsg_job->reply_len = sizeof(struct fc_bsg_reply);
bsg_job->reply->result = DID_OK << 16;
bsg_job->job_done(bsg_job);

return 0;
}

static int
qla2x00_read_i2c(struct fc_bsg_job *bsg_job)
{
struct Scsi_Host *host = bsg_job->shost;
scsi_qla_host_t *vha = shost_priv(host);
struct qla_hw_data *ha = vha->hw;
int rval = 0;
uint8_t bsg[DMA_POOL_SIZE];
struct qla_i2c_access *i2c = (void *)bsg;
dma_addr_t sfp_dma;
uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
if (!sfp) {
bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
EXT_STATUS_NO_MEMORY;
goto done;
}

sg_copy_to_buffer(bsg_job->request_payload.sg_list,
bsg_job->request_payload.sg_cnt, i2c, sizeof(*i2c));

rval = qla2x00_read_sfp(vha, sfp_dma, sfp,
i2c->device, i2c->offset, i2c->length, i2c->option);

if (rval) {
bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
EXT_STATUS_MAILBOX;
goto dealloc;
}

memcpy(i2c->buffer, sfp, i2c->length);
sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
bsg_job->reply_payload.sg_cnt, i2c, sizeof(*i2c));

bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = 0;

dealloc:
dma_pool_free(ha->s_dma_pool, sfp, sfp_dma);

done:
bsg_job->reply_len = sizeof(struct fc_bsg_reply);
bsg_job->reply->reply_payload_rcv_len = sizeof(*i2c);
bsg_job->reply->result = DID_OK << 16;
bsg_job->job_done(bsg_job);

return 0;
}

static int
qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
{
Expand Down Expand Up @@ -1596,6 +1686,12 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
case QL_VND_WRITE_FRU_STATUS:
return qla2x00_write_fru_status(bsg_job);

case QL_VND_WRITE_I2C:
return qla2x00_write_i2c(bsg_job);

case QL_VND_READ_I2C:
return qla2x00_read_i2c(bsg_job);

default:
bsg_job->reply->result = (DID_ERROR << 16);
bsg_job->job_done(bsg_job);
Expand Down
10 changes: 10 additions & 0 deletions drivers/scsi/qla2xxx/qla_bsg.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#define QL_VND_SET_FRU_VERSION 0x0B
#define QL_VND_READ_FRU_STATUS 0x0C
#define QL_VND_WRITE_FRU_STATUS 0x0D
#define QL_VND_WRITE_I2C 0x10
#define QL_VND_READ_I2C 0x11

/* BSG Vendor specific subcode returns */
#define EXT_STATUS_OK 0
Expand Down Expand Up @@ -183,4 +185,12 @@ struct qla_status_reg {
uint8_t reserved[7];
} __packed;

struct qla_i2c_access {
uint16_t device;
uint16_t offset;
uint16_t option;
uint16_t length;
uint8_t buffer[0x40];
} __packed;

#endif

0 comments on commit 9ebb5d9

Please sign in to comment.