aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/ulp
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/ulp')
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h4
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ethtool.c19
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c14
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.h2
-rw-r--r--drivers/infiniband/ulp/iser/iser_memory.c9
-rw-r--r--drivers/infiniband/ulp/iser/iser_verbs.c8
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c42
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.h1
8 files changed, 72 insertions, 27 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 07ca6fd5546b..eb71aaa26a9a 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -117,6 +117,8 @@ enum {
117#define IPOIB_OP_CM (0) 117#define IPOIB_OP_CM (0)
118#endif 118#endif
119 119
120#define IPOIB_QPN_MASK ((__force u32) cpu_to_be32(0xFFFFFF))
121
120/* structs */ 122/* structs */
121 123
122struct ipoib_header { 124struct ipoib_header {
@@ -760,4 +762,6 @@ extern int ipoib_debug_level;
760 762
761#define IPOIB_QPN(ha) (be32_to_cpup((__be32 *) ha) & 0xffffff) 763#define IPOIB_QPN(ha) (be32_to_cpup((__be32 *) ha) & 0xffffff)
762 764
765extern const char ipoib_driver_version[];
766
763#endif /* _IPOIB_H */ 767#endif /* _IPOIB_H */
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
index 29bc7b5724ac..c4b3940845e6 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
@@ -39,7 +39,24 @@
39static void ipoib_get_drvinfo(struct net_device *netdev, 39static void ipoib_get_drvinfo(struct net_device *netdev,
40 struct ethtool_drvinfo *drvinfo) 40 struct ethtool_drvinfo *drvinfo)
41{ 41{
42 strncpy(drvinfo->driver, "ipoib", sizeof(drvinfo->driver) - 1); 42 struct ipoib_dev_priv *priv = netdev_priv(netdev);
43 struct ib_device_attr *attr;
44
45 attr = kmalloc(sizeof(*attr), GFP_KERNEL);
46 if (attr && !ib_query_device(priv->ca, attr))
47 snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
48 "%d.%d.%d", (int)(attr->fw_ver >> 32),
49 (int)(attr->fw_ver >> 16) & 0xffff,
50 (int)attr->fw_ver & 0xffff);
51 kfree(attr);
52
53 strlcpy(drvinfo->bus_info, dev_name(priv->ca->dma_device),
54 sizeof(drvinfo->bus_info));
55
56 strlcpy(drvinfo->version, ipoib_driver_version,
57 sizeof(drvinfo->version));
58
59 strlcpy(drvinfo->driver, "ib_ipoib", sizeof(drvinfo->driver));
43} 60}
44 61
45static int ipoib_get_coalesce(struct net_device *dev, 62static int ipoib_get_coalesce(struct net_device *dev,
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 6fdc9e78da0d..8534afd04e7c 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -49,9 +49,14 @@
49#include <linux/jhash.h> 49#include <linux/jhash.h>
50#include <net/arp.h> 50#include <net/arp.h>
51 51
52#define DRV_VERSION "1.0.0"
53
54const char ipoib_driver_version[] = DRV_VERSION;
55
52MODULE_AUTHOR("Roland Dreier"); 56MODULE_AUTHOR("Roland Dreier");
53MODULE_DESCRIPTION("IP-over-InfiniBand net driver"); 57MODULE_DESCRIPTION("IP-over-InfiniBand net driver");
54MODULE_LICENSE("Dual BSD/GPL"); 58MODULE_LICENSE("Dual BSD/GPL");
59MODULE_VERSION(DRV_VERSION);
55 60
56int ipoib_sendq_size __read_mostly = IPOIB_TX_RING_SIZE; 61int ipoib_sendq_size __read_mostly = IPOIB_TX_RING_SIZE;
57int ipoib_recvq_size __read_mostly = IPOIB_RX_RING_SIZE; 62int ipoib_recvq_size __read_mostly = IPOIB_RX_RING_SIZE;
@@ -505,6 +510,9 @@ static void path_rec_completion(int status,
505 510
506 spin_unlock_irqrestore(&priv->lock, flags); 511 spin_unlock_irqrestore(&priv->lock, flags);
507 512
513 if (IS_ERR_OR_NULL(ah))
514 ipoib_del_neighs_by_gid(dev, path->pathrec.dgid.raw);
515
508 if (old_ah) 516 if (old_ah)
509 ipoib_put_ah(old_ah); 517 ipoib_put_ah(old_ah);
510 518
@@ -844,10 +852,10 @@ static u32 ipoib_addr_hash(struct ipoib_neigh_hash *htbl, u8 *daddr)
844 * different subnets. 852 * different subnets.
845 */ 853 */
846 /* qpn octets[1:4) & port GUID octets[12:20) */ 854 /* qpn octets[1:4) & port GUID octets[12:20) */
847 u32 *daddr_32 = (u32 *) daddr; 855 u32 *d32 = (u32 *) daddr;
848 u32 hv; 856 u32 hv;
849 857
850 hv = jhash_3words(daddr_32[3], daddr_32[4], 0xFFFFFF & daddr_32[0], 0); 858 hv = jhash_3words(d32[3], d32[4], IPOIB_QPN_MASK & d32[0], 0);
851 return hv & htbl->mask; 859 return hv & htbl->mask;
852} 860}
853 861
@@ -1688,6 +1696,8 @@ static void ipoib_remove_one(struct ib_device *device)
1688 return; 1696 return;
1689 1697
1690 dev_list = ib_get_client_data(device, &ipoib_client); 1698 dev_list = ib_get_client_data(device, &ipoib_client);
1699 if (!dev_list)
1700 return;
1691 1701
1692 list_for_each_entry_safe(priv, tmp, dev_list, list) { 1702 list_for_each_entry_safe(priv, tmp, dev_list, list) {
1693 ib_unregister_event_handler(&priv->event_handler); 1703 ib_unregister_event_handler(&priv->event_handler);
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
index ef7d3be46c31..5babdb35bda7 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
@@ -94,7 +94,7 @@
94 94
95 /* support up to 512KB in one RDMA */ 95 /* support up to 512KB in one RDMA */
96#define ISCSI_ISER_SG_TABLESIZE (0x80000 >> SHIFT_4K) 96#define ISCSI_ISER_SG_TABLESIZE (0x80000 >> SHIFT_4K)
97#define ISER_DEF_CMD_PER_LUN 128 97#define ISER_DEF_CMD_PER_LUN ISCSI_DEF_XMIT_CMDS_MAX
98 98
99/* QP settings */ 99/* QP settings */
100/* Maximal bounds on received asynchronous PDUs */ 100/* Maximal bounds on received asynchronous PDUs */
diff --git a/drivers/infiniband/ulp/iser/iser_memory.c b/drivers/infiniband/ulp/iser/iser_memory.c
index 2033a928d34d..be1edb04b085 100644
--- a/drivers/infiniband/ulp/iser/iser_memory.c
+++ b/drivers/infiniband/ulp/iser/iser_memory.c
@@ -369,10 +369,11 @@ int iser_reg_rdma_mem(struct iscsi_iser_task *iser_task,
369 regd_buf = &iser_task->rdma_regd[cmd_dir]; 369 regd_buf = &iser_task->rdma_regd[cmd_dir];
370 370
371 aligned_len = iser_data_buf_aligned_len(mem, ibdev); 371 aligned_len = iser_data_buf_aligned_len(mem, ibdev);
372 if (aligned_len != mem->dma_nents) { 372 if (aligned_len != mem->dma_nents ||
373 (!ib_conn->fmr_pool && mem->dma_nents > 1)) {
373 iscsi_conn->fmr_unalign_cnt++; 374 iscsi_conn->fmr_unalign_cnt++;
374 iser_warn("rdma alignment violation %d/%d aligned\n", 375 iser_warn("rdma alignment violation (%d/%d aligned) or FMR not supported\n",
375 aligned_len, mem->size); 376 aligned_len, mem->size);
376 iser_data_buf_dump(mem, ibdev); 377 iser_data_buf_dump(mem, ibdev);
377 378
378 /* unmap the command data before accessing it */ 379 /* unmap the command data before accessing it */
@@ -404,7 +405,7 @@ int iser_reg_rdma_mem(struct iscsi_iser_task *iser_task,
404 } else { /* use FMR for multiple dma entries */ 405 } else { /* use FMR for multiple dma entries */
405 iser_page_vec_build(mem, ib_conn->page_vec, ibdev); 406 iser_page_vec_build(mem, ib_conn->page_vec, ibdev);
406 err = iser_reg_page_vec(ib_conn, ib_conn->page_vec, &regd_buf->reg); 407 err = iser_reg_page_vec(ib_conn, ib_conn->page_vec, &regd_buf->reg);
407 if (err) { 408 if (err && err != -EAGAIN) {
408 iser_data_buf_dump(mem, ibdev); 409 iser_data_buf_dump(mem, ibdev);
409 iser_err("mem->dma_nents = %d (dlength = 0x%x)\n", 410 iser_err("mem->dma_nents = %d (dlength = 0x%x)\n",
410 mem->dma_nents, 411 mem->dma_nents,
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
index 95a49affee44..4debadc53106 100644
--- a/drivers/infiniband/ulp/iser/iser_verbs.c
+++ b/drivers/infiniband/ulp/iser/iser_verbs.c
@@ -242,10 +242,14 @@ static int iser_create_ib_conn_res(struct iser_conn *ib_conn)
242 IB_ACCESS_REMOTE_READ); 242 IB_ACCESS_REMOTE_READ);
243 243
244 ib_conn->fmr_pool = ib_create_fmr_pool(device->pd, &params); 244 ib_conn->fmr_pool = ib_create_fmr_pool(device->pd, &params);
245 if (IS_ERR(ib_conn->fmr_pool)) { 245 ret = PTR_ERR(ib_conn->fmr_pool);
246 ret = PTR_ERR(ib_conn->fmr_pool); 246 if (IS_ERR(ib_conn->fmr_pool) && ret != -ENOSYS) {
247 ib_conn->fmr_pool = NULL; 247 ib_conn->fmr_pool = NULL;
248 goto out_err; 248 goto out_err;
249 } else if (ret == -ENOSYS) {
250 ib_conn->fmr_pool = NULL;
251 iser_warn("FMRs are not supported, using unaligned mode\n");
252 ret = 0;
249 } 253 }
250 254
251 memset(&init_attr, 0, sizeof init_attr); 255 memset(&init_attr, 0, sizeof init_attr);
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index d5088ce78290..7ccf3284dda3 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -700,23 +700,24 @@ static int srp_reconnect_target(struct srp_target_port *target)
700 struct Scsi_Host *shost = target->scsi_host; 700 struct Scsi_Host *shost = target->scsi_host;
701 int i, ret; 701 int i, ret;
702 702
703 if (target->state != SRP_TARGET_LIVE)
704 return -EAGAIN;
705
706 scsi_target_block(&shost->shost_gendev); 703 scsi_target_block(&shost->shost_gendev);
707 704
708 srp_disconnect_target(target); 705 srp_disconnect_target(target);
709 /* 706 /*
710 * Now get a new local CM ID so that we avoid confusing the 707 * Now get a new local CM ID so that we avoid confusing the target in
711 * target in case things are really fouled up. 708 * case things are really fouled up. Doing so also ensures that all CM
709 * callbacks will have finished before a new QP is allocated.
712 */ 710 */
713 ret = srp_new_cm_id(target); 711 ret = srp_new_cm_id(target);
714 if (ret) 712 /*
715 goto unblock; 713 * Whether or not creating a new CM ID succeeded, create a new
716 714 * QP. This guarantees that all completion callback function
717 ret = srp_create_target_ib(target); 715 * invocations have finished before request resetting starts.
718 if (ret) 716 */
719 goto unblock; 717 if (ret == 0)
718 ret = srp_create_target_ib(target);
719 else
720 srp_create_target_ib(target);
720 721
721 for (i = 0; i < SRP_CMD_SQ_SIZE; ++i) { 722 for (i = 0; i < SRP_CMD_SQ_SIZE; ++i) {
722 struct srp_request *req = &target->req_ring[i]; 723 struct srp_request *req = &target->req_ring[i];
@@ -728,11 +729,12 @@ static int srp_reconnect_target(struct srp_target_port *target)
728 for (i = 0; i < SRP_SQ_SIZE; ++i) 729 for (i = 0; i < SRP_SQ_SIZE; ++i)
729 list_add(&target->tx_ring[i]->list, &target->free_tx); 730 list_add(&target->tx_ring[i]->list, &target->free_tx);
730 731
731 ret = srp_connect_target(target); 732 if (ret == 0)
733 ret = srp_connect_target(target);
732 734
733unblock:
734 scsi_target_unblock(&shost->shost_gendev, ret == 0 ? SDEV_RUNNING : 735 scsi_target_unblock(&shost->shost_gendev, ret == 0 ? SDEV_RUNNING :
735 SDEV_TRANSPORT_OFFLINE); 736 SDEV_TRANSPORT_OFFLINE);
737 target->transport_offline = !!ret;
736 738
737 if (ret) 739 if (ret)
738 goto err; 740 goto err;
@@ -1352,6 +1354,12 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd)
1352 unsigned long flags; 1354 unsigned long flags;
1353 int len; 1355 int len;
1354 1356
1357 if (unlikely(target->transport_offline)) {
1358 scmnd->result = DID_NO_CONNECT << 16;
1359 scmnd->scsi_done(scmnd);
1360 return 0;
1361 }
1362
1355 spin_lock_irqsave(&target->lock, flags); 1363 spin_lock_irqsave(&target->lock, flags);
1356 iu = __srp_get_tx_iu(target, SRP_IU_CMD); 1364 iu = __srp_get_tx_iu(target, SRP_IU_CMD);
1357 if (!iu) 1365 if (!iu)
@@ -1695,6 +1703,9 @@ static int srp_send_tsk_mgmt(struct srp_target_port *target,
1695 struct srp_iu *iu; 1703 struct srp_iu *iu;
1696 struct srp_tsk_mgmt *tsk_mgmt; 1704 struct srp_tsk_mgmt *tsk_mgmt;
1697 1705
1706 if (!target->connected || target->qp_in_error)
1707 return -1;
1708
1698 init_completion(&target->tsk_mgmt_done); 1709 init_completion(&target->tsk_mgmt_done);
1699 1710
1700 spin_lock_irq(&target->lock); 1711 spin_lock_irq(&target->lock);
@@ -1736,7 +1747,7 @@ static int srp_abort(struct scsi_cmnd *scmnd)
1736 1747
1737 shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n"); 1748 shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n");
1738 1749
1739 if (!req || target->qp_in_error || !srp_claim_req(target, req, scmnd)) 1750 if (!req || !srp_claim_req(target, req, scmnd))
1740 return FAILED; 1751 return FAILED;
1741 srp_send_tsk_mgmt(target, req->index, scmnd->device->lun, 1752 srp_send_tsk_mgmt(target, req->index, scmnd->device->lun,
1742 SRP_TSK_ABORT_TASK); 1753 SRP_TSK_ABORT_TASK);
@@ -1754,8 +1765,6 @@ static int srp_reset_device(struct scsi_cmnd *scmnd)
1754 1765
1755 shost_printk(KERN_ERR, target->scsi_host, "SRP reset_device called\n"); 1766 shost_printk(KERN_ERR, target->scsi_host, "SRP reset_device called\n");
1756 1767
1757 if (target->qp_in_error)
1758 return FAILED;
1759 if (srp_send_tsk_mgmt(target, SRP_TAG_NO_REQ, scmnd->device->lun, 1768 if (srp_send_tsk_mgmt(target, SRP_TAG_NO_REQ, scmnd->device->lun,
1760 SRP_TSK_LUN_RESET)) 1769 SRP_TSK_LUN_RESET))
1761 return FAILED; 1770 return FAILED;
@@ -1972,7 +1981,6 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
1972 spin_unlock(&host->target_lock); 1981 spin_unlock(&host->target_lock);
1973 1982
1974 target->state = SRP_TARGET_LIVE; 1983 target->state = SRP_TARGET_LIVE;
1975 target->connected = false;
1976 1984
1977 scsi_scan_target(&target->scsi_host->shost_gendev, 1985 scsi_scan_target(&target->scsi_host->shost_gendev,
1978 0, target->scsi_id, SCAN_WILD_CARD, 0); 1986 0, target->scsi_id, SCAN_WILD_CARD, 0);
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
index de2d0b3c0bfe..66fbedda4571 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -140,6 +140,7 @@ struct srp_target_port {
140 unsigned int cmd_sg_cnt; 140 unsigned int cmd_sg_cnt;
141 unsigned int indirect_size; 141 unsigned int indirect_size;
142 bool allow_ext_sg; 142 bool allow_ext_sg;
143 bool transport_offline;
143 144
144 /* Everything above this point is used in the hot path of 145 /* Everything above this point is used in the hot path of
145 * command processing. Try to keep them packed into cachelines. 146 * command processing. Try to keep them packed into cachelines.