aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx
diff options
context:
space:
mode:
authorJoe Carnuccio <joe.carnuccio@qlogic.com>2012-08-22 14:20:56 -0400
committerJames Bottomley <JBottomley@Parallels.com>2012-09-14 13:28:45 -0400
commit9ebb5d9c69f1f5721f9f6f49e501c674c1e184ae (patch)
treec08ecb3ae2b128bbb5996b651623366ad6756c66 /drivers/scsi/qla2xxx
parent650f528f3581344df96f9b372a7c803919aa7d6f (diff)
[SCSI] qla2xxx: Add I2C BSG interface.
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>
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r--drivers/scsi/qla2xxx/qla_bsg.c96
-rw-r--r--drivers/scsi/qla2xxx/qla_bsg.h10
2 files changed, 106 insertions, 0 deletions
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index c68883806c54..462ac707b8d6 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -1560,6 +1560,96 @@ done:
1560} 1560}
1561 1561
1562static int 1562static int
1563qla2x00_write_i2c(struct fc_bsg_job *bsg_job)
1564{
1565 struct Scsi_Host *host = bsg_job->shost;
1566 scsi_qla_host_t *vha = shost_priv(host);
1567 struct qla_hw_data *ha = vha->hw;
1568 int rval = 0;
1569 uint8_t bsg[DMA_POOL_SIZE];
1570 struct qla_i2c_access *i2c = (void *)bsg;
1571 dma_addr_t sfp_dma;
1572 uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
1573 if (!sfp) {
1574 bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
1575 EXT_STATUS_NO_MEMORY;
1576 goto done;
1577 }
1578
1579 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1580 bsg_job->request_payload.sg_cnt, i2c, sizeof(*i2c));
1581
1582 memcpy(sfp, i2c->buffer, i2c->length);
1583 rval = qla2x00_write_sfp(vha, sfp_dma, sfp,
1584 i2c->device, i2c->offset, i2c->length, i2c->option);
1585
1586 if (rval) {
1587 bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
1588 EXT_STATUS_MAILBOX;
1589 goto dealloc;
1590 }
1591
1592 bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = 0;
1593
1594dealloc:
1595 dma_pool_free(ha->s_dma_pool, sfp, sfp_dma);
1596
1597done:
1598 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
1599 bsg_job->reply->result = DID_OK << 16;
1600 bsg_job->job_done(bsg_job);
1601
1602 return 0;
1603}
1604
1605static int
1606qla2x00_read_i2c(struct fc_bsg_job *bsg_job)
1607{
1608 struct Scsi_Host *host = bsg_job->shost;
1609 scsi_qla_host_t *vha = shost_priv(host);
1610 struct qla_hw_data *ha = vha->hw;
1611 int rval = 0;
1612 uint8_t bsg[DMA_POOL_SIZE];
1613 struct qla_i2c_access *i2c = (void *)bsg;
1614 dma_addr_t sfp_dma;
1615 uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
1616 if (!sfp) {
1617 bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
1618 EXT_STATUS_NO_MEMORY;
1619 goto done;
1620 }
1621
1622 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1623 bsg_job->request_payload.sg_cnt, i2c, sizeof(*i2c));
1624
1625 rval = qla2x00_read_sfp(vha, sfp_dma, sfp,
1626 i2c->device, i2c->offset, i2c->length, i2c->option);
1627
1628 if (rval) {
1629 bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
1630 EXT_STATUS_MAILBOX;
1631 goto dealloc;
1632 }
1633
1634 memcpy(i2c->buffer, sfp, i2c->length);
1635 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
1636 bsg_job->reply_payload.sg_cnt, i2c, sizeof(*i2c));
1637
1638 bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = 0;
1639
1640dealloc:
1641 dma_pool_free(ha->s_dma_pool, sfp, sfp_dma);
1642
1643done:
1644 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
1645 bsg_job->reply->reply_payload_rcv_len = sizeof(*i2c);
1646 bsg_job->reply->result = DID_OK << 16;
1647 bsg_job->job_done(bsg_job);
1648
1649 return 0;
1650}
1651
1652static int
1563qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job) 1653qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
1564{ 1654{
1565 switch (bsg_job->request->rqst_data.h_vendor.vendor_cmd[0]) { 1655 switch (bsg_job->request->rqst_data.h_vendor.vendor_cmd[0]) {
@@ -1596,6 +1686,12 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
1596 case QL_VND_WRITE_FRU_STATUS: 1686 case QL_VND_WRITE_FRU_STATUS:
1597 return qla2x00_write_fru_status(bsg_job); 1687 return qla2x00_write_fru_status(bsg_job);
1598 1688
1689 case QL_VND_WRITE_I2C:
1690 return qla2x00_write_i2c(bsg_job);
1691
1692 case QL_VND_READ_I2C:
1693 return qla2x00_read_i2c(bsg_job);
1694
1599 default: 1695 default:
1600 bsg_job->reply->result = (DID_ERROR << 16); 1696 bsg_job->reply->result = (DID_ERROR << 16);
1601 bsg_job->job_done(bsg_job); 1697 bsg_job->job_done(bsg_job);
diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h
index 70caa63a8930..1a0ab375ce43 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.h
+++ b/drivers/scsi/qla2xxx/qla_bsg.h
@@ -19,6 +19,8 @@
19#define QL_VND_SET_FRU_VERSION 0x0B 19#define QL_VND_SET_FRU_VERSION 0x0B
20#define QL_VND_READ_FRU_STATUS 0x0C 20#define QL_VND_READ_FRU_STATUS 0x0C
21#define QL_VND_WRITE_FRU_STATUS 0x0D 21#define QL_VND_WRITE_FRU_STATUS 0x0D
22#define QL_VND_WRITE_I2C 0x10
23#define QL_VND_READ_I2C 0x11
22 24
23/* BSG Vendor specific subcode returns */ 25/* BSG Vendor specific subcode returns */
24#define EXT_STATUS_OK 0 26#define EXT_STATUS_OK 0
@@ -183,4 +185,12 @@ struct qla_status_reg {
183 uint8_t reserved[7]; 185 uint8_t reserved[7];
184} __packed; 186} __packed;
185 187
188struct qla_i2c_access {
189 uint16_t device;
190 uint16_t offset;
191 uint16_t option;
192 uint16_t length;
193 uint8_t buffer[0x40];
194} __packed;
195
186#endif 196#endif