]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/infiniband/ulp/srp/ib_srp.c
Merge branches 'bart-srp', 'generic-errors', 'ira-cleanups' and 'mwang-v8' into k...
[karo-tx-linux.git] / drivers / infiniband / ulp / srp / ib_srp.c
index 667df9d423eff1168020bfc6196a66324604b5f7..c3f654d20038eaab65ee66da2924e7404ced8c52 100644 (file)
 #define DRV_RELDATE    "July 1, 2013"
 
 MODULE_AUTHOR("Roland Dreier");
-MODULE_DESCRIPTION("InfiniBand SCSI RDMA Protocol initiator "
-                  "v" DRV_VERSION " (" DRV_RELDATE ")");
+MODULE_DESCRIPTION("InfiniBand SCSI RDMA Protocol initiator");
 MODULE_LICENSE("Dual BSD/GPL");
+MODULE_VERSION(DRV_VERSION);
+MODULE_INFO(release_date, DRV_RELDATE);
 
 static unsigned int srp_sg_tablesize;
 static unsigned int cmd_sg_entries;
@@ -466,14 +467,13 @@ static struct srp_fr_pool *srp_alloc_fr_pool(struct srp_target_port *target)
  */
 static void srp_destroy_qp(struct srp_rdma_ch *ch)
 {
-       struct srp_target_port *target = ch->target;
        static struct ib_qp_attr attr = { .qp_state = IB_QPS_ERR };
        static struct ib_recv_wr wr = { .wr_id = SRP_LAST_WR_ID };
        struct ib_recv_wr *bad_wr;
        int ret;
 
        /* Destroying a QP and reusing ch->done is only safe if not connected */
-       WARN_ON_ONCE(target->connected);
+       WARN_ON_ONCE(ch->connected);
 
        ret = ib_modify_qp(ch->qp, &attr, IB_QP_STATE);
        WARN_ONCE(ret, "ib_cm_init_qp_attr() returned %d\n", ret);
@@ -782,7 +782,7 @@ static int srp_send_req(struct srp_rdma_ch *ch, bool multich)
                shost_printk(KERN_DEBUG, target->scsi_host,
                             PFX "Topspin/Cisco initiator port ID workaround "
                             "activated for target GUID %016llx\n",
-                            (unsigned long long) be64_to_cpu(target->ioc_guid));
+                            be64_to_cpu(target->ioc_guid));
                memset(req->priv.initiator_port_id, 0, 8);
                memcpy(req->priv.initiator_port_id + 8,
                       &target->srp_host->srp_dev->dev->node_guid, 8);
@@ -812,35 +812,19 @@ static bool srp_queue_remove_work(struct srp_target_port *target)
        return changed;
 }
 
-static bool srp_change_conn_state(struct srp_target_port *target,
-                                 bool connected)
-{
-       bool changed = false;
-
-       spin_lock_irq(&target->lock);
-       if (target->connected != connected) {
-               target->connected = connected;
-               changed = true;
-       }
-       spin_unlock_irq(&target->lock);
-
-       return changed;
-}
-
 static void srp_disconnect_target(struct srp_target_port *target)
 {
        struct srp_rdma_ch *ch;
        int i;
 
-       if (srp_change_conn_state(target, false)) {
-               /* XXX should send SRP_I_LOGOUT request */
+       /* XXX should send SRP_I_LOGOUT request */
 
-               for (i = 0; i < target->ch_count; i++) {
-                       ch = &target->ch[i];
-                       if (ch->cm_id && ib_send_cm_dreq(ch->cm_id, NULL, 0)) {
-                               shost_printk(KERN_DEBUG, target->scsi_host,
-                                            PFX "Sending CM DREQ failed\n");
-                       }
+       for (i = 0; i < target->ch_count; i++) {
+               ch = &target->ch[i];
+               ch->connected = false;
+               if (ch->cm_id && ib_send_cm_dreq(ch->cm_id, NULL, 0)) {
+                       shost_printk(KERN_DEBUG, target->scsi_host,
+                                    PFX "Sending CM DREQ failed\n");
                }
        }
 }
@@ -853,7 +837,7 @@ static void srp_free_req_data(struct srp_target_port *target,
        struct srp_request *req;
        int i;
 
-       if (!ch->target || !ch->req_ring)
+       if (!ch->req_ring)
                return;
 
        for (i = 0; i < target->req_ring_size; ++i) {
@@ -987,14 +971,26 @@ static void srp_rport_delete(struct srp_rport *rport)
        srp_queue_remove_work(target);
 }
 
+/**
+ * srp_connected_ch() - number of connected channels
+ * @target: SRP target port.
+ */
+static int srp_connected_ch(struct srp_target_port *target)
+{
+       int i, c = 0;
+
+       for (i = 0; i < target->ch_count; i++)
+               c += target->ch[i].connected;
+
+       return c;
+}
+
 static int srp_connect_ch(struct srp_rdma_ch *ch, bool multich)
 {
        struct srp_target_port *target = ch->target;
        int ret;
 
-       WARN_ON_ONCE(!multich && target->connected);
-
-       target->qp_in_error = false;
+       WARN_ON_ONCE(!multich && srp_connected_ch(target) > 0);
 
        ret = srp_lookup_path(ch);
        if (ret)
@@ -1017,7 +1013,7 @@ static int srp_connect_ch(struct srp_rdma_ch *ch, bool multich)
                 */
                switch (ch->status) {
                case 0:
-                       srp_change_conn_state(target, true);
+                       ch->connected = true;
                        return 0;
 
                case SRP_PORT_REDIRECT:
@@ -1215,14 +1211,10 @@ static int srp_rport_reconnect(struct srp_rport *rport)
         */
        for (i = 0; i < target->ch_count; i++) {
                ch = &target->ch[i];
-               if (!ch->target)
-                       break;
                ret += srp_new_cm_id(ch);
        }
        for (i = 0; i < target->ch_count; i++) {
                ch = &target->ch[i];
-               if (!ch->target)
-                       break;
                for (j = 0; j < target->req_ring_size; ++j) {
                        struct srp_request *req = &ch->req_ring[j];
 
@@ -1231,8 +1223,6 @@ static int srp_rport_reconnect(struct srp_rport *rport)
        }
        for (i = 0; i < target->ch_count; i++) {
                ch = &target->ch[i];
-               if (!ch->target)
-                       break;
                /*
                 * Whether or not creating a new CM ID succeeded, create a new
                 * QP. This guarantees that all completion callback function
@@ -1244,13 +1234,13 @@ static int srp_rport_reconnect(struct srp_rport *rport)
                for (j = 0; j < target->queue_size; ++j)
                        list_add(&ch->tx_ring[j]->list, &ch->free_tx);
        }
+
+       target->qp_in_error = false;
+
        for (i = 0; i < target->ch_count; i++) {
                ch = &target->ch[i];
-               if (ret || !ch->target) {
-                       if (i > 1)
-                               ret = 0;
+               if (ret)
                        break;
-               }
                ret = srp_connect_ch(ch, multich);
                multich = true;
        }
@@ -1843,7 +1833,7 @@ static void srp_process_aer_req(struct srp_rdma_ch *ch,
        s32 delta = be32_to_cpu(req->req_lim_delta);
 
        shost_printk(KERN_ERR, target->scsi_host, PFX
-                    "ignoring AER for LUN %llu\n", be64_to_cpu(req->lun));
+                    "ignoring AER for LUN %llu\n", scsilun_to_int(&req->lun));
 
        if (srp_response_common(ch, delta, &rsp, sizeof(rsp)))
                shost_printk(KERN_ERR, target->scsi_host, PFX
@@ -1930,7 +1920,7 @@ static void srp_handle_qp_err(u64 wr_id, enum ib_wc_status wc_status,
                return;
        }
 
-       if (target->connected && !target->qp_in_error) {
+       if (ch->connected && !target->qp_in_error) {
                if (wr_id & LOCAL_INV_WR_ID_MASK) {
                        shost_printk(KERN_ERR, target->scsi_host, PFX
                                     "LOCAL_INV failed with status %s (%d)\n",
@@ -2036,7 +2026,7 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd)
        memset(cmd, 0, sizeof *cmd);
 
        cmd->opcode = SRP_CMD;
-       cmd->lun    = cpu_to_be64((u64) scmnd->device->lun << 48);
+       int_to_scsilun(scmnd->device->lun, &cmd->lun);
        cmd->tag    = tag;
        memcpy(cmd->cdb, scmnd->cmnd, scmnd->cmd_len);
 
@@ -2369,7 +2359,7 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
        case IB_CM_DREQ_RECEIVED:
                shost_printk(KERN_WARNING, target->scsi_host,
                             PFX "DREQ received - connection closed\n");
-               srp_change_conn_state(target, false);
+               ch->connected = false;
                if (ib_send_cm_drep(cm_id, NULL, 0))
                        shost_printk(KERN_ERR, target->scsi_host,
                                     PFX "Sending CM DREP failed\n");
@@ -2416,8 +2406,8 @@ srp_change_queue_depth(struct scsi_device *sdev, int qdepth)
        return scsi_change_queue_depth(sdev, qdepth);
 }
 
-static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag,
-                            unsigned int lun, u8 func)
+static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag, u64 lun,
+                            u8 func)
 {
        struct srp_target_port *target = ch->target;
        struct srp_rport *rport = target->rport;
@@ -2425,7 +2415,7 @@ static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag,
        struct srp_iu *iu;
        struct srp_tsk_mgmt *tsk_mgmt;
 
-       if (!target->connected || target->qp_in_error)
+       if (!ch->connected || target->qp_in_error)
                return -1;
 
        init_completion(&ch->tsk_mgmt_done);
@@ -2451,7 +2441,7 @@ static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag,
        memset(tsk_mgmt, 0, sizeof *tsk_mgmt);
 
        tsk_mgmt->opcode        = SRP_TSK_MGMT;
-       tsk_mgmt->lun           = cpu_to_be64((u64) lun << 48);
+       int_to_scsilun(lun, &tsk_mgmt->lun);
        tsk_mgmt->tag           = req_tag | SRP_TAG_TSK_MGMT;
        tsk_mgmt->tsk_mgmt_func = func;
        tsk_mgmt->task_tag      = req_tag;
@@ -2565,8 +2555,7 @@ static ssize_t show_id_ext(struct device *dev, struct device_attribute *attr,
 {
        struct srp_target_port *target = host_to_target(class_to_shost(dev));
 
-       return sprintf(buf, "0x%016llx\n",
-                      (unsigned long long) be64_to_cpu(target->id_ext));
+       return sprintf(buf, "0x%016llx\n", be64_to_cpu(target->id_ext));
 }
 
 static ssize_t show_ioc_guid(struct device *dev, struct device_attribute *attr,
@@ -2574,8 +2563,7 @@ static ssize_t show_ioc_guid(struct device *dev, struct device_attribute *attr,
 {
        struct srp_target_port *target = host_to_target(class_to_shost(dev));
 
-       return sprintf(buf, "0x%016llx\n",
-                      (unsigned long long) be64_to_cpu(target->ioc_guid));
+       return sprintf(buf, "0x%016llx\n", be64_to_cpu(target->ioc_guid));
 }
 
 static ssize_t show_service_id(struct device *dev,
@@ -2583,8 +2571,7 @@ static ssize_t show_service_id(struct device *dev,
 {
        struct srp_target_port *target = host_to_target(class_to_shost(dev));
 
-       return sprintf(buf, "0x%016llx\n",
-                      (unsigned long long) be64_to_cpu(target->service_id));
+       return sprintf(buf, "0x%016llx\n", be64_to_cpu(target->service_id));
 }
 
 static ssize_t show_pkey(struct device *dev, struct device_attribute *attr,
@@ -2775,7 +2762,7 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
 
        target->state = SRP_TARGET_SCANNING;
        sprintf(target->target_name, "SRP.T10:%016llX",
-                (unsigned long long) be64_to_cpu(target->id_ext));
+               be64_to_cpu(target->id_ext));
 
        if (scsi_add_host(target->scsi_host, host->srp_dev->dev->dma_device))
                return -ENODEV;
@@ -2799,7 +2786,8 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
        scsi_scan_target(&target->scsi_host->shost_gendev,
                         0, target->scsi_id, SCAN_WILD_CARD, 0);
 
-       if (!target->connected || target->qp_in_error) {
+       if (srp_connected_ch(target) < target->ch_count ||
+           target->qp_in_error) {
                shost_printk(KERN_INFO, target->scsi_host,
                             PFX "SCSI scan failed - removing SCSI host\n");
                srp_queue_remove_work(target);
@@ -3148,7 +3136,7 @@ static ssize_t srp_create_target(struct device *dev,
        target_host->transportt  = ib_srp_transport_template;
        target_host->max_channel = 0;
        target_host->max_id      = 1;
-       target_host->max_lun     = SRP_MAX_LUN;
+       target_host->max_lun     = -1LL;
        target_host->max_cmd_len = sizeof ((struct srp_cmd *) (void *) 0L)->cdb;
 
        target = host_to_target(target_host);
@@ -3174,11 +3162,11 @@ static ssize_t srp_create_target(struct device *dev,
 
        ret = srp_parse_options(buf, target);
        if (ret)
-               goto err;
+               goto out;
 
        ret = scsi_init_shared_tag_map(target_host, target_host->can_queue);
        if (ret)
-               goto err;
+               goto out;
 
        target->req_ring_size = target->queue_size - SRP_TSK_MGMT_SQ_SIZE;
 
@@ -3189,7 +3177,7 @@ static ssize_t srp_create_target(struct device *dev,
                             be64_to_cpu(target->ioc_guid),
                             be64_to_cpu(target->initiator_ext));
                ret = -EEXIST;
-               goto err;
+               goto out;
        }
 
        if (!srp_dev->has_fmr && !srp_dev->has_fr && !target->allow_ext_sg &&
@@ -3210,7 +3198,7 @@ static ssize_t srp_create_target(struct device *dev,
        spin_lock_init(&target->lock);
        ret = ib_query_gid(ibdev, host->port, 0, &target->sgid);
        if (ret)
-               goto err;
+               goto out;
 
        ret = -ENOMEM;
        target->ch_count = max_t(unsigned, num_online_nodes(),
@@ -3221,7 +3209,7 @@ static ssize_t srp_create_target(struct device *dev,
        target->ch = kcalloc(target->ch_count, sizeof(*target->ch),
                             GFP_KERNEL);
        if (!target->ch)
-               goto err;
+               goto out;
 
        node_idx = 0;
        for_each_online_node(node) {
@@ -3317,9 +3305,6 @@ err_disconnect:
        }
 
        kfree(target->ch);
-
-err:
-       scsi_host_put(target_host);
        goto out;
 }