diff options
author | Joe Carnuccio <joe.carnuccio@qlogic.com> | 2012-08-22 14:20:56 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-09-14 13:28:45 -0400 |
commit | 9ebb5d9c69f1f5721f9f6f49e501c674c1e184ae (patch) | |
tree | c08ecb3ae2b128bbb5996b651623366ad6756c66 /drivers/scsi/qla2xxx | |
parent | 650f528f3581344df96f9b372a7c803919aa7d6f (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.c | 96 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_bsg.h | 10 |
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 | ||
1562 | static int | 1562 | static int |
1563 | qla2x00_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 | |||
1594 | dealloc: | ||
1595 | dma_pool_free(ha->s_dma_pool, sfp, sfp_dma); | ||
1596 | |||
1597 | done: | ||
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 | |||
1605 | static int | ||
1606 | qla2x00_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 | |||
1640 | dealloc: | ||
1641 | dma_pool_free(ha->s_dma_pool, sfp, sfp_dma); | ||
1642 | |||
1643 | done: | ||
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 | |||
1652 | static int | ||
1563 | qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job) | 1653 | qla2x00_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 | ||
188 | struct 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 |