Pārlūkot izejas kodu

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
Linus Torvalds 18 gadi atpakaļ
vecāks
revīzija
cabe456902

+ 2 - 2
drivers/s390/scsi/zfcp_aux.c

@@ -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);
 }
 
 /**

+ 3 - 7
drivers/s390/scsi/zfcp_qdio.c

@@ -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);
 }
 
 /**

+ 3 - 1
drivers/s390/scsi/zfcp_scsi.c

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

+ 52 - 13
drivers/scsi/libiscsi.c

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

+ 9 - 12
drivers/scsi/qla2xxx/qla_dbg.c

@@ -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++));
 }
 
 

+ 0 - 1
drivers/scsi/qla2xxx/qla_def.h

@@ -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;
 

+ 19 - 9
drivers/scsi/qla2xxx/qla_gs.c

@@ -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. */

+ 15 - 36
drivers/scsi/qla2xxx/qla_init.c

@@ -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 */

+ 1 - 0
drivers/scsi/qla2xxx/qla_isr.c

@@ -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 */

+ 1 - 1
drivers/scsi/qla2xxx/qla_os.c

@@ -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;
 

+ 1 - 1
drivers/scsi/qla2xxx/qla_version.h

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

+ 7 - 0
include/scsi/libiscsi.h

@@ -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;