]> pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 27 Jul 2008 17:04:52 +0000 (10:04 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 27 Jul 2008 17:04:52 +0000 (10:04 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (59 commits)
  [SCSI] replace __FUNCTION__ with __func__
  [SCSI] extend the last_sector_bug flag to cover more sectors
  [SCSI] qla2xxx: Update version number to 8.02.01-k6.
  [SCSI] qla2xxx: Additional NPIV corrections.
  [SCSI] qla2xxx: suppress uninitialized-var warning
  [SCSI] qla2xxx: use memory_read_from_buffer()
  [SCSI] qla2xxx: Issue proper ISP callbacks during stop-firmware.
  [SCSI] ch: fix ch_remove oops
  [SCSI] 3w-9xxx: add MSI support and misc fixes
  [SCSI] scsi_lib: use blk_rq_tagged in scsi_request_fn
  [SCSI] ibmvfc: Update driver version to 1.0.1
  [SCSI] ibmvfc: Add ADISC support
  [SCSI] ibmvfc: Miscellaneous fixes
  [SCSI] ibmvfc: Fix hang on module removal
  [SCSI] ibmvfc: Target refcounting fixes
  [SCSI] ibmvfc: Reduce unnecessary log noise
  [SCSI] sym53c8xx: free luntbl in sym_hcb_free
  [SCSI] scsi_scan.c: Release mutex in error handling code
  [SCSI] scsi_eh_prep_cmnd should save scmd->underflow
  [SCSI] sd: Support for SCSI disk (SBC) Data Integrity Field
  ...

1  2 
drivers/scsi/ibmvscsi/ibmvfc.c
drivers/scsi/ibmvscsi/ibmvstgt.c

index 61f8fdea2d96e24824bb2926e1f4cd126912377f,a33fa133f75b19f3a4500d4d2ae6fb58f2b5cb52..ae560bc04f9d4df009ad8aef36abfa288dfca2f2
@@@ -521,9 -521,10 +521,10 @@@ static void ibmvfc_set_host_action(stru
  static void ibmvfc_reinit_host(struct ibmvfc_host *vhost)
  {
        if (vhost->action == IBMVFC_HOST_ACTION_NONE) {
-               scsi_block_requests(vhost->host);
-               ibmvfc_set_host_state(vhost, IBMVFC_INITIALIZING);
-               ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY);
+               if (!ibmvfc_set_host_state(vhost, IBMVFC_INITIALIZING)) {
+                       scsi_block_requests(vhost->host);
+                       ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY);
+               }
        } else
                vhost->reinit = 1;
  
@@@ -854,39 -855,41 +855,41 @@@ static void ibmvfc_retry_host_init(stru
  }
  
  /**
-  * __ibmvfc_find_target - Find the specified scsi_target (no locking)
+  * __ibmvfc_get_target - Find the specified scsi_target (no locking)
   * @starget:  scsi target struct
   *
   * Return value:
   *    ibmvfc_target struct / NULL if not found
   **/
- static struct ibmvfc_target *__ibmvfc_find_target(struct scsi_target *starget)
+ static struct ibmvfc_target *__ibmvfc_get_target(struct scsi_target *starget)
  {
        struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
        struct ibmvfc_host *vhost = shost_priv(shost);
        struct ibmvfc_target *tgt;
  
        list_for_each_entry(tgt, &vhost->targets, queue)
-               if (tgt->target_id == starget->id)
+               if (tgt->target_id == starget->id) {
+                       kref_get(&tgt->kref);
                        return tgt;
+               }
        return NULL;
  }
  
  /**
-  * ibmvfc_find_target - Find the specified scsi_target
+  * ibmvfc_get_target - Find the specified scsi_target
   * @starget:  scsi target struct
   *
   * Return value:
   *    ibmvfc_target struct / NULL if not found
   **/
- static struct ibmvfc_target *ibmvfc_find_target(struct scsi_target *starget)
+ static struct ibmvfc_target *ibmvfc_get_target(struct scsi_target *starget)
  {
        struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
        struct ibmvfc_target *tgt;
        unsigned long flags;
  
        spin_lock_irqsave(shost->host_lock, flags);
-       tgt = __ibmvfc_find_target(starget);
+       tgt = __ibmvfc_get_target(starget);
        spin_unlock_irqrestore(shost->host_lock, flags);
        return tgt;
  }
@@@ -963,6 -966,9 +966,9 @@@ static void ibmvfc_get_host_port_state(
        case IBMVFC_HALTED:
                fc_host_port_state(shost) = FC_PORTSTATE_BLOCKED;
                break;
+       case IBMVFC_NO_CRQ:
+               fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
+               break;
        default:
                ibmvfc_log(vhost, 3, "Unknown port state: %d\n", vhost->state);
                fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
@@@ -987,6 -993,17 +993,17 @@@ static void ibmvfc_set_rport_dev_loss_t
                rport->dev_loss_tmo = 1;
  }
  
+ /**
+  * ibmvfc_release_tgt - Free memory allocated for a target
+  * @kref:             kref struct
+  *
+  **/
+ static void ibmvfc_release_tgt(struct kref *kref)
+ {
+       struct ibmvfc_target *tgt = container_of(kref, struct ibmvfc_target, kref);
+       kfree(tgt);
+ }
  /**
   * ibmvfc_get_starget_node_name - Get SCSI target's node name
   * @starget:  scsi target struct
   **/
  static void ibmvfc_get_starget_node_name(struct scsi_target *starget)
  {
-       struct ibmvfc_target *tgt = ibmvfc_find_target(starget);
+       struct ibmvfc_target *tgt = ibmvfc_get_target(starget);
        fc_starget_port_name(starget) = tgt ? tgt->ids.node_name : 0;
+       if (tgt)
+               kref_put(&tgt->kref, ibmvfc_release_tgt);
  }
  
  /**
   **/
  static void ibmvfc_get_starget_port_name(struct scsi_target *starget)
  {
-       struct ibmvfc_target *tgt = ibmvfc_find_target(starget);
+       struct ibmvfc_target *tgt = ibmvfc_get_target(starget);
        fc_starget_port_name(starget) = tgt ? tgt->ids.port_name : 0;
+       if (tgt)
+               kref_put(&tgt->kref, ibmvfc_release_tgt);
  }
  
  /**
   **/
  static void ibmvfc_get_starget_port_id(struct scsi_target *starget)
  {
-       struct ibmvfc_target *tgt = ibmvfc_find_target(starget);
+       struct ibmvfc_target *tgt = ibmvfc_get_target(starget);
        fc_starget_port_id(starget) = tgt ? tgt->scsi_id : -1;
+       if (tgt)
+               kref_put(&tgt->kref, ibmvfc_release_tgt);
  }
  
  /**
@@@ -1113,7 -1136,7 +1136,7 @@@ static void ibmvfc_set_login_info(struc
        login_info->max_cmds = max_requests + IBMVFC_NUM_INTERNAL_REQ;
        login_info->capabilities = IBMVFC_CAN_MIGRATE;
        login_info->async.va = vhost->async_crq.msg_token;
-       login_info->async.len = vhost->async_crq.size;
+       login_info->async.len = vhost->async_crq.size * sizeof(*vhost->async_crq.msgs);
        strncpy(login_info->partition_name, vhost->partition_name, IBMVFC_MAX_NAME);
        strncpy(login_info->device_name,
                vhost->host->shost_gendev.bus_id, IBMVFC_MAX_NAME);
@@@ -1404,7 -1427,7 +1427,7 @@@ static void ibmvfc_log_error(struct ibm
                err = cmd_status[index].name;
        }
  
-       if (!logerr && (vhost->log_level <= IBMVFC_DEFAULT_LOG_LEVEL))
+       if (!logerr && (vhost->log_level <= (IBMVFC_DEFAULT_LOG_LEVEL + 1)))
                return;
  
        if (rsp->flags & FCP_RSP_LEN_VALID)
@@@ -2054,7 -2077,7 +2077,7 @@@ static void ibmvfc_handle_async(struct 
  {
        const char *desc = ibmvfc_get_ae_desc(crq->event);
  
-       ibmvfc_log(vhost, 2, "%s event received\n", desc);
+       ibmvfc_log(vhost, 3, "%s event received\n", desc);
  
        switch (crq->event) {
        case IBMVFC_AE_LINK_UP:
@@@ -2647,17 -2670,6 +2670,6 @@@ static void ibmvfc_retry_tgt_init(struc
                ibmvfc_init_tgt(tgt, job_step);
  }
  
- /**
-  * ibmvfc_release_tgt - Free memory allocated for a target
-  * @kref:             kref struct
-  *
-  **/
- static void ibmvfc_release_tgt(struct kref *kref)
- {
-       struct ibmvfc_target *tgt = container_of(kref, struct ibmvfc_target, kref);
-       kfree(tgt);
- }
  /**
   * ibmvfc_tgt_prli_done - Completion handler for Process Login
   * @evt:      ibmvfc event struct
@@@ -2901,6 -2913,139 +2913,139 @@@ static void ibmvfc_tgt_implicit_logout(
                tgt_dbg(tgt, "Sent Implicit Logout\n");
  }
  
+ /**
+  * ibmvfc_adisc_needs_plogi - Does device need PLOGI?
+  * @mad:      ibmvfc passthru mad struct
+  * @tgt:      ibmvfc target struct
+  *
+  * Returns:
+  *    1 if PLOGI needed / 0 if PLOGI not needed
+  **/
+ static int ibmvfc_adisc_needs_plogi(struct ibmvfc_passthru_mad *mad,
+                                   struct ibmvfc_target *tgt)
+ {
+       if (memcmp(&mad->fc_iu.response[2], &tgt->ids.port_name,
+                  sizeof(tgt->ids.port_name)))
+               return 1;
+       if (memcmp(&mad->fc_iu.response[4], &tgt->ids.node_name,
+                  sizeof(tgt->ids.node_name)))
+               return 1;
+       if (mad->fc_iu.response[6] != tgt->scsi_id)
+               return 1;
+       return 0;
+ }
+ /**
+  * ibmvfc_tgt_adisc_done - Completion handler for ADISC
+  * @evt:      ibmvfc event struct
+  *
+  **/
+ static void ibmvfc_tgt_adisc_done(struct ibmvfc_event *evt)
+ {
+       struct ibmvfc_target *tgt = evt->tgt;
+       struct ibmvfc_host *vhost = evt->vhost;
+       struct ibmvfc_passthru_mad *mad = &evt->xfer_iu->passthru;
+       u32 status = mad->common.status;
+       u8 fc_reason, fc_explain;
+       vhost->discovery_threads--;
+       ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
+       switch (status) {
+       case IBMVFC_MAD_SUCCESS:
+               tgt_dbg(tgt, "ADISC succeeded\n");
+               if (ibmvfc_adisc_needs_plogi(mad, tgt))
+                       tgt->need_login = 1;
+               break;
+       case IBMVFC_MAD_DRIVER_FAILED:
+               break;
+       case IBMVFC_MAD_FAILED:
+       default:
+               tgt->need_login = 1;
+               fc_reason = (mad->fc_iu.response[1] & 0x00ff0000) >> 16;
+               fc_explain = (mad->fc_iu.response[1] & 0x0000ff00) >> 8;
+               tgt_info(tgt, "ADISC failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n",
+                        ibmvfc_get_cmd_error(mad->iu.status, mad->iu.error),
+                        mad->iu.status, mad->iu.error,
+                        ibmvfc_get_fc_type(fc_reason), fc_reason,
+                        ibmvfc_get_ls_explain(fc_explain), fc_explain, status);
+               break;
+       };
+       kref_put(&tgt->kref, ibmvfc_release_tgt);
+       ibmvfc_free_event(evt);
+       wake_up(&vhost->work_wait_q);
+ }
+ /**
+  * ibmvfc_init_passthru - Initialize an event struct for FC passthru
+  * @evt:              ibmvfc event struct
+  *
+  **/
+ static void ibmvfc_init_passthru(struct ibmvfc_event *evt)
+ {
+       struct ibmvfc_passthru_mad *mad = &evt->iu.passthru;
+       memset(mad, 0, sizeof(*mad));
+       mad->common.version = 1;
+       mad->common.opcode = IBMVFC_PASSTHRU;
+       mad->common.length = sizeof(*mad) - sizeof(mad->fc_iu) - sizeof(mad->iu);
+       mad->cmd_ioba.va = (u64)evt->crq.ioba +
+               offsetof(struct ibmvfc_passthru_mad, iu);
+       mad->cmd_ioba.len = sizeof(mad->iu);
+       mad->iu.cmd_len = sizeof(mad->fc_iu.payload);
+       mad->iu.rsp_len = sizeof(mad->fc_iu.response);
+       mad->iu.cmd.va = (u64)evt->crq.ioba +
+               offsetof(struct ibmvfc_passthru_mad, fc_iu) +
+               offsetof(struct ibmvfc_passthru_fc_iu, payload);
+       mad->iu.cmd.len = sizeof(mad->fc_iu.payload);
+       mad->iu.rsp.va = (u64)evt->crq.ioba +
+               offsetof(struct ibmvfc_passthru_mad, fc_iu) +
+               offsetof(struct ibmvfc_passthru_fc_iu, response);
+       mad->iu.rsp.len = sizeof(mad->fc_iu.response);
+ }
+ /**
+  * ibmvfc_tgt_adisc - Initiate an ADISC for specified target
+  * @tgt:              ibmvfc target struct
+  *
+  **/
+ static void ibmvfc_tgt_adisc(struct ibmvfc_target *tgt)
+ {
+       struct ibmvfc_passthru_mad *mad;
+       struct ibmvfc_host *vhost = tgt->vhost;
+       struct ibmvfc_event *evt;
+       if (vhost->discovery_threads >= disc_threads)
+               return;
+       kref_get(&tgt->kref);
+       evt = ibmvfc_get_event(vhost);
+       vhost->discovery_threads++;
+       ibmvfc_init_event(evt, ibmvfc_tgt_adisc_done, IBMVFC_MAD_FORMAT);
+       evt->tgt = tgt;
+       ibmvfc_init_passthru(evt);
+       mad = &evt->iu.passthru;
+       mad->iu.flags = IBMVFC_FC_ELS;
+       mad->iu.scsi_id = tgt->scsi_id;
+       mad->fc_iu.payload[0] = IBMVFC_ADISC;
+       memcpy(&mad->fc_iu.payload[2], &vhost->login_buf->resp.port_name,
+              sizeof(vhost->login_buf->resp.port_name));
+       memcpy(&mad->fc_iu.payload[4], &vhost->login_buf->resp.node_name,
+              sizeof(vhost->login_buf->resp.node_name));
+       mad->fc_iu.payload[6] = vhost->login_buf->resp.scsi_id & 0x00ffffff;
+       ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT);
+       if (ibmvfc_send_event(evt, vhost, default_timeout)) {
+               vhost->discovery_threads--;
+               ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
+               kref_put(&tgt->kref, ibmvfc_release_tgt);
+       } else
+               tgt_dbg(tgt, "Sent ADISC\n");
+ }
  /**
   * ibmvfc_tgt_query_target_done - Completion handler for Query Target MAD
   * @evt:      ibmvfc event struct
@@@ -2921,6 -3066,8 +3066,8 @@@ static void ibmvfc_tgt_query_target_don
                tgt->new_scsi_id = rsp->scsi_id;
                if (rsp->scsi_id != tgt->scsi_id)
                        ibmvfc_init_tgt(tgt, ibmvfc_tgt_implicit_logout);
+               else
+                       ibmvfc_init_tgt(tgt, ibmvfc_tgt_adisc);
                break;
        case IBMVFC_MAD_DRIVER_FAILED:
                break;
@@@ -3336,6 -3483,7 +3483,7 @@@ static void ibmvfc_tgt_add_rport(struc
                tgt_dbg(tgt, "rport add succeeded\n");
                rport->maxframe_size = tgt->service_parms.common.bb_rcv_sz & 0x0fff;
                rport->supported_classes = 0;
+               tgt->target_id = rport->scsi_target_id;
                if (tgt->service_parms.class1_parms[0] & 0x80000000)
                        rport->supported_classes |= FC_COS_CLASS1;
                if (tgt->service_parms.class2_parms[0] & 0x80000000)
@@@ -3525,7 -3673,7 +3673,7 @@@ static int ibmvfc_init_crq(struct ibmvf
        crq->msg_token = dma_map_single(dev, crq->msgs,
                                        PAGE_SIZE, DMA_BIDIRECTIONAL);
  
 -      if (dma_mapping_error(crq->msg_token))
 +      if (dma_mapping_error(dev, crq->msg_token))
                goto map_failed;
  
        retrc = rc = plpar_hcall_norets(H_REG_CRQ, vdev->unit_address,
@@@ -3618,7 -3766,7 +3766,7 @@@ static int ibmvfc_alloc_mem(struct ibmv
                                            async_q->size * sizeof(*async_q->msgs),
                                            DMA_BIDIRECTIONAL);
  
 -      if (dma_mapping_error(async_q->msg_token)) {
 +      if (dma_mapping_error(dev, async_q->msg_token)) {
                dev_err(dev, "Failed to map async queue\n");
                goto free_async_crq;
        }
@@@ -3800,10 -3948,12 +3948,12 @@@ static int ibmvfc_remove(struct vio_de
  
        ENTER;
        ibmvfc_remove_trace_file(&vhost->host->shost_dev.kobj, &ibmvfc_trace_attr);
+       ibmvfc_link_down(vhost, IBMVFC_HOST_OFFLINE);
+       ibmvfc_wait_while_resetting(vhost);
+       ibmvfc_release_crq_queue(vhost);
        kthread_stop(vhost->work_thread);
        fc_remove_host(vhost->host);
        scsi_remove_host(vhost->host);
-       ibmvfc_release_crq_queue(vhost);
  
        spin_lock_irqsave(vhost->host->host_lock, flags);
        ibmvfc_purge_requests(vhost, DID_ERROR);
index 2e13ec00172aca14ccdea9da8daf6ed339e179ef,d6f68f22cf743cfb329edb08f2e5424e04955ac3..2a5b29d12172e4a72bb774453d2662b7d29192ee
@@@ -55,7 -55,7 +55,7 @@@
  /* tmp - will replace with SCSI logging stuff */
  #define eprintk(fmt, args...)                                 \
  do {                                                          \
-       printk("%s(%d) " fmt, __FUNCTION__, __LINE__, ##args);  \
+       printk("%s(%d) " fmt, __func__, __LINE__, ##args);      \
  } while (0)
  /* #define dprintk eprintk */
  #define dprintk(fmt, args...)
@@@ -564,7 -564,7 +564,7 @@@ static int crq_queue_create(struct crq_
                                          queue->size * sizeof(*queue->msgs),
                                          DMA_BIDIRECTIONAL);
  
 -      if (dma_mapping_error(queue->msg_token))
 +      if (dma_mapping_error(target->dev, queue->msg_token))
                goto map_failed;
  
        err = h_reg_crq(vport->dma_dev->unit_address, queue->msg_token,