diff options
Diffstat (limited to 'drivers/scsi/ibmvscsi/ibmvscsi.c')
-rw-r--r-- | drivers/scsi/ibmvscsi/ibmvscsi.c | 81 |
1 files changed, 61 insertions, 20 deletions
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 5ecc63d1b436..cda0cc3d182f 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c | |||
@@ -70,11 +70,13 @@ | |||
70 | #include <linux/moduleparam.h> | 70 | #include <linux/moduleparam.h> |
71 | #include <linux/dma-mapping.h> | 71 | #include <linux/dma-mapping.h> |
72 | #include <linux/delay.h> | 72 | #include <linux/delay.h> |
73 | #include <asm/firmware.h> | ||
73 | #include <asm/vio.h> | 74 | #include <asm/vio.h> |
74 | #include <scsi/scsi.h> | 75 | #include <scsi/scsi.h> |
75 | #include <scsi/scsi_cmnd.h> | 76 | #include <scsi/scsi_cmnd.h> |
76 | #include <scsi/scsi_host.h> | 77 | #include <scsi/scsi_host.h> |
77 | #include <scsi/scsi_device.h> | 78 | #include <scsi/scsi_device.h> |
79 | #include <scsi/scsi_transport_srp.h> | ||
78 | #include "ibmvscsi.h" | 80 | #include "ibmvscsi.h" |
79 | 81 | ||
80 | /* The values below are somewhat arbitrary default values, but | 82 | /* The values below are somewhat arbitrary default values, but |
@@ -87,8 +89,12 @@ static int max_channel = 3; | |||
87 | static int init_timeout = 5; | 89 | static int init_timeout = 5; |
88 | static int max_requests = IBMVSCSI_MAX_REQUESTS_DEFAULT; | 90 | static int max_requests = IBMVSCSI_MAX_REQUESTS_DEFAULT; |
89 | 91 | ||
92 | static struct scsi_transport_template *ibmvscsi_transport_template; | ||
93 | |||
90 | #define IBMVSCSI_VERSION "1.5.8" | 94 | #define IBMVSCSI_VERSION "1.5.8" |
91 | 95 | ||
96 | static struct ibmvscsi_ops *ibmvscsi_ops; | ||
97 | |||
92 | MODULE_DESCRIPTION("IBM Virtual SCSI"); | 98 | MODULE_DESCRIPTION("IBM Virtual SCSI"); |
93 | MODULE_AUTHOR("Dave Boutcher"); | 99 | MODULE_AUTHOR("Dave Boutcher"); |
94 | MODULE_LICENSE("GPL"); | 100 | MODULE_LICENSE("GPL"); |
@@ -506,8 +512,8 @@ static void ibmvscsi_reset_host(struct ibmvscsi_host_data *hostdata) | |||
506 | atomic_set(&hostdata->request_limit, 0); | 512 | atomic_set(&hostdata->request_limit, 0); |
507 | 513 | ||
508 | purge_requests(hostdata, DID_ERROR); | 514 | purge_requests(hostdata, DID_ERROR); |
509 | if ((ibmvscsi_reset_crq_queue(&hostdata->queue, hostdata)) || | 515 | if ((ibmvscsi_ops->reset_crq_queue(&hostdata->queue, hostdata)) || |
510 | (ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0)) || | 516 | (ibmvscsi_ops->send_crq(hostdata, 0xC001000000000000LL, 0)) || |
511 | (vio_enable_interrupts(to_vio_dev(hostdata->dev)))) { | 517 | (vio_enable_interrupts(to_vio_dev(hostdata->dev)))) { |
512 | atomic_set(&hostdata->request_limit, -1); | 518 | atomic_set(&hostdata->request_limit, -1); |
513 | dev_err(hostdata->dev, "error after reset\n"); | 519 | dev_err(hostdata->dev, "error after reset\n"); |
@@ -612,7 +618,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct, | |||
612 | } | 618 | } |
613 | 619 | ||
614 | if ((rc = | 620 | if ((rc = |
615 | ibmvscsi_send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) { | 621 | ibmvscsi_ops->send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) { |
616 | list_del(&evt_struct->list); | 622 | list_del(&evt_struct->list); |
617 | del_timer(&evt_struct->timer); | 623 | del_timer(&evt_struct->timer); |
618 | 624 | ||
@@ -1211,8 +1217,8 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq, | |||
1211 | case 0x01: /* Initialization message */ | 1217 | case 0x01: /* Initialization message */ |
1212 | dev_info(hostdata->dev, "partner initialized\n"); | 1218 | dev_info(hostdata->dev, "partner initialized\n"); |
1213 | /* Send back a response */ | 1219 | /* Send back a response */ |
1214 | if ((rc = ibmvscsi_send_crq(hostdata, | 1220 | if ((rc = ibmvscsi_ops->send_crq(hostdata, |
1215 | 0xC002000000000000LL, 0)) == 0) { | 1221 | 0xC002000000000000LL, 0)) == 0) { |
1216 | /* Now login */ | 1222 | /* Now login */ |
1217 | send_srp_login(hostdata); | 1223 | send_srp_login(hostdata); |
1218 | } else { | 1224 | } else { |
@@ -1237,10 +1243,10 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq, | |||
1237 | /* We need to re-setup the interpartition connection */ | 1243 | /* We need to re-setup the interpartition connection */ |
1238 | dev_info(hostdata->dev, "Re-enabling adapter!\n"); | 1244 | dev_info(hostdata->dev, "Re-enabling adapter!\n"); |
1239 | purge_requests(hostdata, DID_REQUEUE); | 1245 | purge_requests(hostdata, DID_REQUEUE); |
1240 | if ((ibmvscsi_reenable_crq_queue(&hostdata->queue, | 1246 | if ((ibmvscsi_ops->reenable_crq_queue(&hostdata->queue, |
1241 | hostdata)) || | 1247 | hostdata)) || |
1242 | (ibmvscsi_send_crq(hostdata, | 1248 | (ibmvscsi_ops->send_crq(hostdata, |
1243 | 0xC001000000000000LL, 0))) { | 1249 | 0xC001000000000000LL, 0))) { |
1244 | atomic_set(&hostdata->request_limit, | 1250 | atomic_set(&hostdata->request_limit, |
1245 | -1); | 1251 | -1); |
1246 | dev_err(hostdata->dev, "error after enable\n"); | 1252 | dev_err(hostdata->dev, "error after enable\n"); |
@@ -1250,10 +1256,10 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq, | |||
1250 | crq->format); | 1256 | crq->format); |
1251 | 1257 | ||
1252 | purge_requests(hostdata, DID_ERROR); | 1258 | purge_requests(hostdata, DID_ERROR); |
1253 | if ((ibmvscsi_reset_crq_queue(&hostdata->queue, | 1259 | if ((ibmvscsi_ops->reset_crq_queue(&hostdata->queue, |
1254 | hostdata)) || | 1260 | hostdata)) || |
1255 | (ibmvscsi_send_crq(hostdata, | 1261 | (ibmvscsi_ops->send_crq(hostdata, |
1256 | 0xC001000000000000LL, 0))) { | 1262 | 0xC001000000000000LL, 0))) { |
1257 | atomic_set(&hostdata->request_limit, | 1263 | atomic_set(&hostdata->request_limit, |
1258 | -1); | 1264 | -1); |
1259 | dev_err(hostdata->dev, "error after reset\n"); | 1265 | dev_err(hostdata->dev, "error after reset\n"); |
@@ -1553,6 +1559,8 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
1553 | struct ibmvscsi_host_data *hostdata; | 1559 | struct ibmvscsi_host_data *hostdata; |
1554 | struct Scsi_Host *host; | 1560 | struct Scsi_Host *host; |
1555 | struct device *dev = &vdev->dev; | 1561 | struct device *dev = &vdev->dev; |
1562 | struct srp_rport_identifiers ids; | ||
1563 | struct srp_rport *rport; | ||
1556 | unsigned long wait_switch = 0; | 1564 | unsigned long wait_switch = 0; |
1557 | int rc; | 1565 | int rc; |
1558 | 1566 | ||
@@ -1565,6 +1573,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
1565 | goto scsi_host_alloc_failed; | 1573 | goto scsi_host_alloc_failed; |
1566 | } | 1574 | } |
1567 | 1575 | ||
1576 | host->transportt = ibmvscsi_transport_template; | ||
1568 | hostdata = shost_priv(host); | 1577 | hostdata = shost_priv(host); |
1569 | memset(hostdata, 0x00, sizeof(*hostdata)); | 1578 | memset(hostdata, 0x00, sizeof(*hostdata)); |
1570 | INIT_LIST_HEAD(&hostdata->sent); | 1579 | INIT_LIST_HEAD(&hostdata->sent); |
@@ -1573,7 +1582,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
1573 | atomic_set(&hostdata->request_limit, -1); | 1582 | atomic_set(&hostdata->request_limit, -1); |
1574 | hostdata->host->max_sectors = 32 * 8; /* default max I/O 32 pages */ | 1583 | hostdata->host->max_sectors = 32 * 8; /* default max I/O 32 pages */ |
1575 | 1584 | ||
1576 | rc = ibmvscsi_init_crq_queue(&hostdata->queue, hostdata, max_requests); | 1585 | rc = ibmvscsi_ops->init_crq_queue(&hostdata->queue, hostdata, max_requests); |
1577 | if (rc != 0 && rc != H_RESOURCE) { | 1586 | if (rc != 0 && rc != H_RESOURCE) { |
1578 | dev_err(&vdev->dev, "couldn't initialize crq. rc=%d\n", rc); | 1587 | dev_err(&vdev->dev, "couldn't initialize crq. rc=%d\n", rc); |
1579 | goto init_crq_failed; | 1588 | goto init_crq_failed; |
@@ -1590,11 +1599,19 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
1590 | if (scsi_add_host(hostdata->host, hostdata->dev)) | 1599 | if (scsi_add_host(hostdata->host, hostdata->dev)) |
1591 | goto add_host_failed; | 1600 | goto add_host_failed; |
1592 | 1601 | ||
1602 | /* we don't have a proper target_port_id so let's use the fake one */ | ||
1603 | memcpy(ids.port_id, hostdata->madapter_info.partition_name, | ||
1604 | sizeof(ids.port_id)); | ||
1605 | ids.roles = SRP_RPORT_ROLE_TARGET; | ||
1606 | rport = srp_rport_add(host, &ids); | ||
1607 | if (IS_ERR(rport)) | ||
1608 | goto add_srp_port_failed; | ||
1609 | |||
1593 | /* Try to send an initialization message. Note that this is allowed | 1610 | /* Try to send an initialization message. Note that this is allowed |
1594 | * to fail if the other end is not acive. In that case we don't | 1611 | * to fail if the other end is not acive. In that case we don't |
1595 | * want to scan | 1612 | * want to scan |
1596 | */ | 1613 | */ |
1597 | if (ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0) == 0 | 1614 | if (ibmvscsi_ops->send_crq(hostdata, 0xC001000000000000LL, 0) == 0 |
1598 | || rc == H_RESOURCE) { | 1615 | || rc == H_RESOURCE) { |
1599 | /* | 1616 | /* |
1600 | * Wait around max init_timeout secs for the adapter to finish | 1617 | * Wait around max init_timeout secs for the adapter to finish |
@@ -1617,10 +1634,12 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
1617 | vdev->dev.driver_data = hostdata; | 1634 | vdev->dev.driver_data = hostdata; |
1618 | return 0; | 1635 | return 0; |
1619 | 1636 | ||
1637 | add_srp_port_failed: | ||
1638 | scsi_remove_host(hostdata->host); | ||
1620 | add_host_failed: | 1639 | add_host_failed: |
1621 | release_event_pool(&hostdata->pool, hostdata); | 1640 | release_event_pool(&hostdata->pool, hostdata); |
1622 | init_pool_failed: | 1641 | init_pool_failed: |
1623 | ibmvscsi_release_crq_queue(&hostdata->queue, hostdata, max_requests); | 1642 | ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata, max_requests); |
1624 | init_crq_failed: | 1643 | init_crq_failed: |
1625 | scsi_host_put(host); | 1644 | scsi_host_put(host); |
1626 | scsi_host_alloc_failed: | 1645 | scsi_host_alloc_failed: |
@@ -1631,9 +1650,10 @@ static int ibmvscsi_remove(struct vio_dev *vdev) | |||
1631 | { | 1650 | { |
1632 | struct ibmvscsi_host_data *hostdata = vdev->dev.driver_data; | 1651 | struct ibmvscsi_host_data *hostdata = vdev->dev.driver_data; |
1633 | release_event_pool(&hostdata->pool, hostdata); | 1652 | release_event_pool(&hostdata->pool, hostdata); |
1634 | ibmvscsi_release_crq_queue(&hostdata->queue, hostdata, | 1653 | ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata, |
1635 | max_requests); | 1654 | max_requests); |
1636 | 1655 | ||
1656 | srp_remove_host(hostdata->host); | ||
1637 | scsi_remove_host(hostdata->host); | 1657 | scsi_remove_host(hostdata->host); |
1638 | scsi_host_put(hostdata->host); | 1658 | scsi_host_put(hostdata->host); |
1639 | 1659 | ||
@@ -1660,14 +1680,35 @@ static struct vio_driver ibmvscsi_driver = { | |||
1660 | } | 1680 | } |
1661 | }; | 1681 | }; |
1662 | 1682 | ||
1683 | static struct srp_function_template ibmvscsi_transport_functions = { | ||
1684 | }; | ||
1685 | |||
1663 | int __init ibmvscsi_module_init(void) | 1686 | int __init ibmvscsi_module_init(void) |
1664 | { | 1687 | { |
1665 | return vio_register_driver(&ibmvscsi_driver); | 1688 | int ret; |
1689 | |||
1690 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | ||
1691 | ibmvscsi_ops = &iseriesvscsi_ops; | ||
1692 | else if (firmware_has_feature(FW_FEATURE_VIO)) | ||
1693 | ibmvscsi_ops = &rpavscsi_ops; | ||
1694 | else | ||
1695 | return -ENODEV; | ||
1696 | |||
1697 | ibmvscsi_transport_template = | ||
1698 | srp_attach_transport(&ibmvscsi_transport_functions); | ||
1699 | if (!ibmvscsi_transport_template) | ||
1700 | return -ENOMEM; | ||
1701 | |||
1702 | ret = vio_register_driver(&ibmvscsi_driver); | ||
1703 | if (ret) | ||
1704 | srp_release_transport(ibmvscsi_transport_template); | ||
1705 | return ret; | ||
1666 | } | 1706 | } |
1667 | 1707 | ||
1668 | void __exit ibmvscsi_module_exit(void) | 1708 | void __exit ibmvscsi_module_exit(void) |
1669 | { | 1709 | { |
1670 | vio_unregister_driver(&ibmvscsi_driver); | 1710 | vio_unregister_driver(&ibmvscsi_driver); |
1711 | srp_release_transport(ibmvscsi_transport_template); | ||
1671 | } | 1712 | } |
1672 | 1713 | ||
1673 | module_init(ibmvscsi_module_init); | 1714 | module_init(ibmvscsi_module_init); |