Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6:
  [SCSI] libiscsi: sync up iscsi and scsi eh's access to the connection
  [SCSI] libiscsi: fix null ptr regression when aborting a command with data to transfer
  [SCSI] qla2xxx: Update version number to 8.02.00-k3.
  [SCSI] qla2xxx: Correct mailbox register dump for FWI2 capable ISPs.
  [SCSI] qla2xxx: Correct 8GB iIDMA support.
  [SCSI] qla2xxx: Correct management-server login-state synchronization issue.
  [SCSI] qla2xxx: Don't modify parity bits during ISP25XX restart.
  [SCSI] qla2xxx: Allocate enough space for the full PCI descriptor.
  [SCSI] zfcp: fix the data buffer accessor patch
  [SCSI] zfcp: allocate gid_pn_data objects from gid_pn_cache
  [SCSI] zfcp: fix memory leak
This commit is contained in:
Linus Torvalds 2007-09-11 07:46:09 -07:00
commit cabe456902
12 changed files with 113 additions and 83 deletions

View file

@ -1503,7 +1503,7 @@ zfcp_gid_pn_buffers_alloc(struct zfcp_gid_pn_data **gid_pn, mempool_t *pool)
data->ct.pool = pool;
}
} else {
data = kmalloc(sizeof(struct zfcp_gid_pn_data), GFP_ATOMIC);
data = kmem_cache_alloc(zfcp_data.gid_pn_cache, GFP_ATOMIC);
}
if (NULL == data)
@ -1531,7 +1531,7 @@ static void zfcp_gid_pn_buffers_free(struct zfcp_gid_pn_data *gid_pn)
if (gid_pn->ct.pool)
mempool_free(gid_pn, gid_pn->ct.pool);
else
kfree(gid_pn);
kmem_cache_free(zfcp_data.gid_pn_cache, gid_pn);
}
/**

View file

@ -640,13 +640,9 @@ int
zfcp_qdio_sbals_from_scsicmnd(struct zfcp_fsf_req *fsf_req,
unsigned long sbtype, struct scsi_cmnd *scsi_cmnd)
{
if (scsi_sg_count(scsi_cmnd))
return zfcp_qdio_sbals_from_sg(fsf_req, sbtype,
scsi_sglist(scsi_cmnd),
scsi_sg_count(scsi_cmnd),
ZFCP_MAX_SBALS_PER_REQ);
else
return 0;
return zfcp_qdio_sbals_from_sg(fsf_req, sbtype, scsi_sglist(scsi_cmnd),
scsi_sg_count(scsi_cmnd),
ZFCP_MAX_SBALS_PER_REQ);
}
/**

View file

@ -764,7 +764,9 @@ zfcp_reset_fc_host_stats(struct Scsi_Host *shost)
return;
ret = zfcp_fsf_exchange_port_data(NULL, adapter, data);
if (ret == 0) {
if (ret) {
kfree(data);
} else {
adapter->stats_reset = jiffies/HZ;
old_data = adapter->stats_reset_data;
adapter->stats_reset_data = data; /* finally freed in

View file

@ -737,12 +737,19 @@ check_mgmt:
*/
conn->ctask = list_entry(conn->xmitqueue.next,
struct iscsi_cmd_task, running);
if (conn->ctask->state == ISCSI_TASK_PENDING) {
switch (conn->ctask->state) {
case ISCSI_TASK_ABORTING:
break;
case ISCSI_TASK_PENDING:
iscsi_prep_scsi_cmd_pdu(conn->ctask);
conn->session->tt->init_cmd_task(conn->ctask);
/* fall through */
default:
conn->ctask->state = ISCSI_TASK_RUNNING;
break;
}
conn->ctask->state = ISCSI_TASK_RUNNING;
list_move_tail(conn->xmitqueue.next, &conn->run_list);
rc = iscsi_xmit_ctask(conn);
if (rc)
goto again;
@ -1049,7 +1056,9 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc,
ctask->mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr,
NULL, 0);
if (!ctask->mtask) {
spin_unlock_bh(&session->lock);
iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
spin_lock_bh(&session->lock)
debug_scsi("abort sent failure [itt 0x%x]\n", ctask->itt);
return -EPERM;
}
@ -1066,6 +1075,7 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc,
debug_scsi("abort set timeout [itt 0x%x]\n", ctask->itt);
}
spin_unlock_bh(&session->lock);
mutex_unlock(&session->eh_mutex);
scsi_queue_work(session->host, &conn->xmitwork);
/*
@ -1083,6 +1093,7 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc,
if (signal_pending(current))
flush_signals(current);
del_timer_sync(&conn->tmabort_timer);
mutex_lock(&session->eh_mutex);
spin_lock_bh(&session->lock);
return 0;
}
@ -1158,31 +1169,45 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
__iscsi_put_ctask(ctask);
}
static void iscsi_suspend_tx(struct iscsi_conn *conn)
{
set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
scsi_flush_work(conn->session->host);
}
static void iscsi_start_tx(struct iscsi_conn *conn)
{
clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
scsi_queue_work(conn->session->host, &conn->xmitwork);
}
int iscsi_eh_abort(struct scsi_cmnd *sc)
{
struct Scsi_Host *host = sc->device->host;
struct iscsi_session *session = iscsi_hostdata(host->hostdata);
struct iscsi_cmd_task *ctask;
struct iscsi_conn *conn;
struct iscsi_session *session;
int rc;
mutex_lock(&session->eh_mutex);
spin_lock_bh(&session->lock);
/*
* if session was ISCSI_STATE_IN_RECOVERY then we may not have
* got the command.
*/
if (!sc->SCp.ptr) {
debug_scsi("sc never reached iscsi layer or it completed.\n");
spin_unlock_bh(&session->lock);
mutex_unlock(&session->eh_mutex);
return SUCCESS;
}
ctask = (struct iscsi_cmd_task *)sc->SCp.ptr;
conn = ctask->conn;
session = conn->session;
conn->eh_abort_cnt++;
debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt);
spin_lock_bh(&session->lock);
/*
* If we are not logged in or we have started a new session
* then let the host reset code handle this
@ -1219,6 +1244,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
switch (conn->tmabort_state) {
case TMABORT_SUCCESS:
spin_unlock_bh(&session->lock);
iscsi_suspend_tx(conn);
/*
* clean up task if aborted. grab the recv lock as a writer
*/
@ -1227,11 +1253,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
fail_command(conn, ctask, DID_ABORT << 16);
spin_unlock(&session->lock);
write_unlock_bh(conn->recv_lock);
/*
* make sure xmit thread is not still touching the
* ctask/scsi_cmnd
*/
scsi_flush_work(session->host);
iscsi_start_tx(conn);
goto success_unlocked;
case TMABORT_NOT_FOUND:
if (!ctask->sc) {
@ -1251,12 +1273,14 @@ success:
spin_unlock_bh(&session->lock);
success_unlocked:
debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
mutex_unlock(&session->eh_mutex);
return SUCCESS;
failed:
spin_unlock_bh(&session->lock);
failed_unlocked:
debug_scsi("abort failed [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
mutex_unlock(&session->eh_mutex);
return FAILED;
}
EXPORT_SYMBOL_GPL(iscsi_eh_abort);
@ -1403,6 +1427,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
session->max_cmdsn = initial_cmdsn + 1;
session->max_r2t = 1;
session->tt = iscsit;
mutex_init(&session->eh_mutex);
/* initialize SCSI PDU commands pool */
if (iscsi_pool_init(&session->cmdpool, session->cmds_max,
@ -1736,9 +1761,22 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
{
int old_stop_stage;
mutex_lock(&session->eh_mutex);
spin_lock_bh(&session->lock);
if (conn->stop_stage == STOP_CONN_TERM) {
spin_unlock_bh(&session->lock);
mutex_unlock(&session->eh_mutex);
return;
}
/*
* The LLD either freed/unset the lock on us, or userspace called
* stop but did not create a proper connection (connection was never
* bound or it was unbound then stop was called).
*/
if (!conn->recv_lock) {
spin_unlock_bh(&session->lock);
mutex_unlock(&session->eh_mutex);
return;
}
@ -1755,9 +1793,9 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
old_stop_stage = conn->stop_stage;
conn->stop_stage = flag;
conn->c_stage = ISCSI_CONN_STOPPED;
set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
spin_unlock_bh(&session->lock);
scsi_flush_work(session->host);
iscsi_suspend_tx(conn);
write_lock_bh(conn->recv_lock);
set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
@ -1786,6 +1824,7 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
fail_all_commands(conn);
flush_control_queues(session, conn);
spin_unlock_bh(&session->lock);
mutex_unlock(&session->eh_mutex);
}
void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)

View file

@ -2050,21 +2050,18 @@ qla25xx_fw_dump_failed:
void
qla2x00_dump_regs(scsi_qla_host_t *ha)
{
int i;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24;
uint16_t __iomem *mbx_reg;
mbx_reg = IS_FWI2_CAPABLE(ha) ? &reg24->mailbox0:
MAILBOX_REG(ha, reg, 0);
printk("Mailbox registers:\n");
printk("scsi(%ld): mbox 0 0x%04x \n",
ha->host_no, RD_MAILBOX_REG(ha, reg, 0));
printk("scsi(%ld): mbox 1 0x%04x \n",
ha->host_no, RD_MAILBOX_REG(ha, reg, 1));
printk("scsi(%ld): mbox 2 0x%04x \n",
ha->host_no, RD_MAILBOX_REG(ha, reg, 2));
printk("scsi(%ld): mbox 3 0x%04x \n",
ha->host_no, RD_MAILBOX_REG(ha, reg, 3));
printk("scsi(%ld): mbox 4 0x%04x \n",
ha->host_no, RD_MAILBOX_REG(ha, reg, 4));
printk("scsi(%ld): mbox 5 0x%04x \n",
ha->host_no, RD_MAILBOX_REG(ha, reg, 5));
for (i = 0; i < 6; i++)
printk("scsi(%ld): mbox %d 0x%04x \n", ha->host_no, i,
RD_REG_WORD(mbx_reg++));
}

View file

@ -1502,7 +1502,6 @@ typedef struct {
uint8_t node_name[WWN_SIZE];
uint8_t port_name[WWN_SIZE];
uint8_t fabric_port_name[WWN_SIZE];
uint16_t fp_speeds;
uint16_t fp_speed;
} sw_info_t;

View file

@ -295,6 +295,8 @@ qla2x00_gid_pt(scsi_qla_host_t *ha, sw_info_t *list)
list[i].d_id.b.domain = gid_data->port_id[0];
list[i].d_id.b.area = gid_data->port_id[1];
list[i].d_id.b.al_pa = gid_data->port_id[2];
memset(list[i].fabric_port_name, 0, WWN_SIZE);
list[i].fp_speed = PORT_SPEED_UNKNOWN;
/* Last one exit. */
if (gid_data->control_byte & BIT_7) {
@ -1707,8 +1709,6 @@ qla2x00_gfpn_id(scsi_qla_host_t *ha, sw_info_t *list)
for (i = 0; i < MAX_FIBRE_DEVICES; i++) {
/* Issue GFPN_ID */
memset(list[i].fabric_port_name, 0, WWN_SIZE);
/* Prepare common MS IOCB */
ms_pkt = ha->isp_ops->prep_ms_iocb(ha, GFPN_ID_REQ_SIZE,
GFPN_ID_RSP_SIZE);
@ -1821,8 +1821,6 @@ qla2x00_gpsc(scsi_qla_host_t *ha, sw_info_t *list)
for (i = 0; i < MAX_FIBRE_DEVICES; i++) {
/* Issue GFPN_ID */
list[i].fp_speeds = list[i].fp_speed = 0;
/* Prepare common MS IOCB */
ms_pkt = qla24xx_prep_ms_fm_iocb(ha, GPSC_REQ_SIZE,
GPSC_RSP_SIZE);
@ -1858,9 +1856,21 @@ qla2x00_gpsc(scsi_qla_host_t *ha, sw_info_t *list)
}
rval = QLA_FUNCTION_FAILED;
} else {
/* Save portname */
list[i].fp_speeds = ct_rsp->rsp.gpsc.speeds;
list[i].fp_speed = ct_rsp->rsp.gpsc.speed;
/* Save port-speed */
switch (be16_to_cpu(ct_rsp->rsp.gpsc.speed)) {
case BIT_15:
list[i].fp_speed = PORT_SPEED_1GB;
break;
case BIT_14:
list[i].fp_speed = PORT_SPEED_2GB;
break;
case BIT_13:
list[i].fp_speed = PORT_SPEED_4GB;
break;
case BIT_11:
list[i].fp_speed = PORT_SPEED_8GB;
break;
}
DEBUG2_3(printk("scsi(%ld): GPSC ext entry - "
"fpn %02x%02x%02x%02x%02x%02x%02x%02x speeds=%04x "
@ -1873,8 +1883,8 @@ qla2x00_gpsc(scsi_qla_host_t *ha, sw_info_t *list)
list[i].fabric_port_name[5],
list[i].fabric_port_name[6],
list[i].fabric_port_name[7],
be16_to_cpu(list[i].fp_speeds),
be16_to_cpu(list[i].fp_speed)));
be16_to_cpu(ct_rsp->rsp.gpsc.speeds),
be16_to_cpu(ct_rsp->rsp.gpsc.speed)));
}
/* Last device exit. */

View file

@ -2079,17 +2079,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha)
}
/* Base iIDMA settings on HBA port speed. */
switch (ha->link_data_rate) {
case PORT_SPEED_1GB:
fcport->fp_speed = cpu_to_be16(BIT_15);
break;
case PORT_SPEED_2GB:
fcport->fp_speed = cpu_to_be16(BIT_14);
break;
case PORT_SPEED_4GB:
fcport->fp_speed = cpu_to_be16(BIT_13);
break;
}
fcport->fp_speed = ha->link_data_rate;
qla2x00_update_fcport(ha, fcport);
@ -2130,38 +2120,25 @@ static void
qla2x00_iidma_fcport(scsi_qla_host_t *ha, fc_port_t *fcport)
{
#define LS_UNKNOWN 2
static char *link_speeds[5] = { "1", "2", "?", "4" };
static char *link_speeds[5] = { "1", "2", "?", "4", "8" };
int rval;
uint16_t port_speed, mb[6];
uint16_t mb[6];
if (!IS_IIDMA_CAPABLE(ha))
return;
switch (be16_to_cpu(fcport->fp_speed)) {
case BIT_15:
port_speed = PORT_SPEED_1GB;
break;
case BIT_14:
port_speed = PORT_SPEED_2GB;
break;
case BIT_13:
port_speed = PORT_SPEED_4GB;
break;
default:
if (fcport->fp_speed == PORT_SPEED_UNKNOWN) {
DEBUG2(printk("scsi(%ld): %02x%02x%02x%02x%02x%02x%02x%02x -- "
"unsupported FM port operating speed (%04x).\n",
"unsupported FM port operating speed.\n",
ha->host_no, fcport->port_name[0], fcport->port_name[1],
fcport->port_name[2], fcport->port_name[3],
fcport->port_name[4], fcport->port_name[5],
fcport->port_name[6], fcport->port_name[7],
be16_to_cpu(fcport->fp_speed)));
port_speed = PORT_SPEED_UNKNOWN;
break;
}
if (port_speed == PORT_SPEED_UNKNOWN)
fcport->port_name[6], fcport->port_name[7]));
return;
}
rval = qla2x00_set_idma_speed(ha, fcport->loop_id, port_speed, mb);
rval = qla2x00_set_idma_speed(ha, fcport->loop_id, fcport->fp_speed,
mb);
if (rval != QLA_SUCCESS) {
DEBUG2(printk("scsi(%ld): Unable to adjust iIDMA "
"%02x%02x%02x%02x%02x%02x%02x%02x -- %04x %x %04x %04x.\n",
@ -2169,12 +2146,12 @@ qla2x00_iidma_fcport(scsi_qla_host_t *ha, fc_port_t *fcport)
fcport->port_name[2], fcport->port_name[3],
fcport->port_name[4], fcport->port_name[5],
fcport->port_name[6], fcport->port_name[7], rval,
port_speed, mb[0], mb[1]));
fcport->fp_speed, mb[0], mb[1]));
} else {
DEBUG2(qla_printk(KERN_INFO, ha,
"iIDMA adjusted to %s GB/s on "
"%02x%02x%02x%02x%02x%02x%02x%02x.\n",
link_speeds[port_speed], fcport->port_name[0],
link_speeds[fcport->fp_speed], fcport->port_name[0],
fcport->port_name[1], fcport->port_name[2],
fcport->port_name[3], fcport->port_name[4],
fcport->port_name[5], fcport->port_name[6],
@ -3354,7 +3331,8 @@ qla2x00_restart_isp(scsi_qla_host_t *ha)
spin_lock_irqsave(&ha->hardware_lock, flags);
if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) {
if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha) &&
!IS_QLA25XX(ha)) {
/*
* Disable SRAM, Instruction RAM and GP RAM
* parity.
@ -3370,7 +3348,8 @@ qla2x00_restart_isp(scsi_qla_host_t *ha)
spin_lock_irqsave(&ha->hardware_lock, flags);
if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) {
if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha) &&
!IS_QLA25XX(ha)) {
/* Enable proper parity */
if (IS_QLA2300(ha))
/* SRAM parity */

View file

@ -490,6 +490,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
ha->flags.gpsc_supported = 1;
ha->flags.management_server_logged_in = 0;
break;
case MBA_CHG_IN_CONNECTION: /* Change in connection mode */

View file

@ -1564,7 +1564,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
struct Scsi_Host *host;
scsi_qla_host_t *ha;
unsigned long flags = 0;
char pci_info[20];
char pci_info[30];
char fw_str[30];
struct scsi_host_template *sht;

View file

@ -7,7 +7,7 @@
/*
* Driver version
*/
#define QLA2XXX_VERSION "8.02.00-k2"
#define QLA2XXX_VERSION "8.02.00-k3"
#define QLA_DRIVER_MAJOR_VER 8
#define QLA_DRIVER_MINOR_VER 2

View file

@ -205,6 +205,13 @@ struct iscsi_queue {
};
struct iscsi_session {
/*
* Syncs up the scsi eh thread with the iscsi eh thread when sending
* task management functions. This must be taken before the session
* and recv lock.
*/
struct mutex eh_mutex;
/* iSCSI session-wide sequencing */
uint32_t cmdsn;
uint32_t exp_cmdsn;