Skip to content

Commit

Permalink
[SCSI] qla2xxx: Provide method for updating I2C attached VPD.
Browse files Browse the repository at this point in the history
Provide bsg interface for updating VPD attached on the I2C serial bus.

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 Aug 29, 2011
1 parent 1fedd80 commit 697a4bc
Show file tree
Hide file tree
Showing 2 changed files with 193 additions and 0 deletions.
151 changes: 151 additions & 0 deletions drivers/scsi/qla2xxx/qla_bsg.c
Original file line number Diff line number Diff line change
Expand Up @@ -1447,6 +1447,148 @@ qla2x00_update_optrom(struct fc_bsg_job *bsg_job)
return rval;
}

static int
qla2x00_update_fru_versions(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_image_version_list *list = (void *)bsg;
struct qla_image_version *image;
uint32_t count;
dma_addr_t sfp_dma;
void *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, list, sizeof(bsg));

image = list->version;
count = list->count;
while (count--) {
memcpy(sfp, &image->field_info, sizeof(image->field_info));
rval = qla2x00_write_sfp(vha, sfp_dma, sfp,
image->field_address.device, image->field_address.offset,
sizeof(image->field_info), image->field_address.option);
if (rval) {
bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
EXT_STATUS_MAILBOX;
goto dealloc;
}
image++;
}

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_fru_status(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_status_reg *sr = (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, sr, sizeof(*sr));

rval = qla2x00_read_sfp(vha, sfp_dma, sfp,
sr->field_address.device, sr->field_address.offset,
sizeof(sr->status_reg), sr->field_address.option);
sr->status_reg = *sfp;

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

sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
bsg_job->reply_payload.sg_cnt, sr, sizeof(*sr));

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(*sr);
bsg_job->reply->result = DID_OK << 16;
bsg_job->job_done(bsg_job);

return 0;
}

static int
qla2x00_write_fru_status(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_status_reg *sr = (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, sr, sizeof(*sr));

*sfp = sr->status_reg;
rval = qla2x00_write_sfp(vha, sfp_dma, sfp,
sr->field_address.device, sr->field_address.offset,
sizeof(sr->status_reg), sr->field_address.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_process_vendor_specific(struct fc_bsg_job *bsg_job)
{
Expand Down Expand Up @@ -1475,6 +1617,15 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
case QL_VND_UPDATE_FLASH:
return qla2x00_update_optrom(bsg_job);

case QL_VND_SET_FRU_VERSION:
return qla2x00_update_fru_versions(bsg_job);

case QL_VND_READ_FRU_STATUS:
return qla2x00_read_fru_status(bsg_job);

case QL_VND_WRITE_FRU_STATUS:
return qla2x00_write_fru_status(bsg_job);

default:
bsg_job->reply->result = (DID_ERROR << 16);
bsg_job->job_done(bsg_job);
Expand Down
42 changes: 42 additions & 0 deletions drivers/scsi/qla2xxx/qla_bsg.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@
#define QL_VND_FCP_PRIO_CFG_CMD 0x06
#define QL_VND_READ_FLASH 0x07
#define QL_VND_UPDATE_FLASH 0x08
#define QL_VND_SET_FRU_VERSION 0x0B
#define QL_VND_READ_FRU_STATUS 0x0C
#define QL_VND_WRITE_FRU_STATUS 0x0D

/* BSG Vendor specific subcode returns */
#define EXT_STATUS_OK 0
#define EXT_STATUS_ERR 1
#define EXT_STATUS_INVALID_PARAM 6
#define EXT_STATUS_MAILBOX 11
#define EXT_STATUS_NO_MEMORY 17

/* BSG definations for interpreting CommandSent field */
#define INT_DEF_LB_LOOPBACK_CMD 0
Expand Down Expand Up @@ -141,4 +151,36 @@ struct qla_port_param {
uint16_t mode;
uint16_t speed;
} __attribute__ ((packed));


/* FRU VPD */

#define MAX_FRU_SIZE 36

struct qla_field_address {
uint16_t offset;
uint16_t device;
uint16_t option;
} __packed;

struct qla_field_info {
uint8_t version[MAX_FRU_SIZE];
} __packed;

struct qla_image_version {
struct qla_field_address field_address;
struct qla_field_info field_info;
} __packed;

struct qla_image_version_list {
uint32_t count;
struct qla_image_version version[0];
} __packed;

struct qla_status_reg {
struct qla_field_address field_address;
uint8_t status_reg;
uint8_t reserved[7];
} __packed;

#endif

0 comments on commit 697a4bc

Please sign in to comment.