Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6

* 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
  ...
This commit is contained in:
Linus Torvalds
2008-07-27 10:04:52 -07:00
91 changed files with 3961 additions and 1044 deletions

View File

@@ -521,9 +521,10 @@ static void ibmvfc_set_host_action(struct ibmvfc_host *vhost,
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 @@ static void ibmvfc_retry_host_init(struct ibmvfc_host *vhost)
}
/**
* __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 @@ static void ibmvfc_get_host_port_state(struct Scsi_Host *shost)
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 @@ static void ibmvfc_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout)
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
@@ -996,8 +1013,10 @@ static void ibmvfc_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout)
**/
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);
}
/**
@@ -1009,8 +1028,10 @@ static void ibmvfc_get_starget_node_name(struct scsi_target *starget)
**/
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);
}
/**
@@ -1022,8 +1043,10 @@ static void ibmvfc_get_starget_port_name(struct scsi_target *starget)
**/
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 @@ static void ibmvfc_set_login_info(struct ibmvfc_host *vhost)
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 @@ static void ibmvfc_log_error(struct ibmvfc_event *evt)
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 @@ static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq,
{
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 @@ static void ibmvfc_retry_tgt_init(struct ibmvfc_target *tgt,
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 @@ static void ibmvfc_tgt_implicit_logout(struct ibmvfc_target *tgt)
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 @@ static void ibmvfc_tgt_query_target_done(struct ibmvfc_event *evt)
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 @@ static void ibmvfc_tgt_add_rport(struct ibmvfc_target *tgt)
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)
@@ -3800,10 +3948,12 @@ static int ibmvfc_remove(struct vio_dev *vdev)
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);

View File

@@ -29,8 +29,8 @@
#include "viosrp.h"
#define IBMVFC_NAME "ibmvfc"
#define IBMVFC_DRIVER_VERSION "1.0.0"
#define IBMVFC_DRIVER_DATE "(July 1, 2008)"
#define IBMVFC_DRIVER_VERSION "1.0.1"
#define IBMVFC_DRIVER_DATE "(July 11, 2008)"
#define IBMVFC_DEFAULT_TIMEOUT 15
#define IBMVFC_INIT_TIMEOUT 30
@@ -119,6 +119,7 @@ enum ibmvfc_mad_types {
IBMVFC_PROCESS_LOGIN = 0x0008,
IBMVFC_QUERY_TARGET = 0x0010,
IBMVFC_IMPLICIT_LOGOUT = 0x0040,
IBMVFC_PASSTHRU = 0x0200,
IBMVFC_TMF_MAD = 0x0100,
};
@@ -439,6 +440,37 @@ struct ibmvfc_cmd {
struct ibmvfc_fcp_rsp rsp;
}__attribute__((packed, aligned (8)));
struct ibmvfc_passthru_fc_iu {
u32 payload[7];
#define IBMVFC_ADISC 0x52000000
u32 response[7];
};
struct ibmvfc_passthru_iu {
u64 task_tag;
u32 cmd_len;
u32 rsp_len;
u16 status;
u16 error;
u32 flags;
#define IBMVFC_FC_ELS 0x01
u32 cancel_key;
u32 reserved;
struct srp_direct_buf cmd;
struct srp_direct_buf rsp;
u64 correlation;
u64 scsi_id;
u64 tag;
u64 reserved2[2];
}__attribute__((packed, aligned (8)));
struct ibmvfc_passthru_mad {
struct ibmvfc_mad_common common;
struct srp_direct_buf cmd_ioba;
struct ibmvfc_passthru_iu iu;
struct ibmvfc_passthru_fc_iu fc_iu;
}__attribute__((packed, aligned (8)));
struct ibmvfc_trace_start_entry {
u32 xfer_len;
}__attribute__((packed));
@@ -531,6 +563,7 @@ union ibmvfc_iu {
struct ibmvfc_implicit_logout implicit_logout;
struct ibmvfc_tmf tmf;
struct ibmvfc_cmd cmd;
struct ibmvfc_passthru_mad passthru;
}__attribute__((packed, aligned (8)));
enum ibmvfc_target_action {
@@ -656,6 +689,9 @@ struct ibmvfc_host {
#define tgt_dbg(t, fmt, ...) \
DBG_CMD(dev_info((t)->vhost->dev, "%lX: " fmt, (t)->scsi_id, ##__VA_ARGS__))
#define tgt_info(t, fmt, ...) \
dev_info((t)->vhost->dev, "%lX: " fmt, (t)->scsi_id, ##__VA_ARGS__)
#define tgt_err(t, fmt, ...) \
dev_err((t)->vhost->dev, "%lX: " fmt, (t)->scsi_id, ##__VA_ARGS__)
@@ -668,8 +704,8 @@ struct ibmvfc_host {
dev_err((vhost)->dev, ##__VA_ARGS__); \
} while (0)
#define ENTER DBG_CMD(printk(KERN_INFO IBMVFC_NAME": Entering %s\n", __FUNCTION__))
#define LEAVE DBG_CMD(printk(KERN_INFO IBMVFC_NAME": Leaving %s\n", __FUNCTION__))
#define ENTER DBG_CMD(printk(KERN_INFO IBMVFC_NAME": Entering %s\n", __func__))
#define LEAVE DBG_CMD(printk(KERN_INFO IBMVFC_NAME": Leaving %s\n", __func__))
#ifdef CONFIG_SCSI_IBMVFC_TRACE
#define ibmvfc_create_trace_file(kobj, attr) sysfs_create_bin_file(kobj, attr)

View File

@@ -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...)