Skip to contentSkip to conversation

zfcp updates for 2.6.35 merge window

PATCH New Christof Schmitt 1 participant 6 messages Apr 30, 2010

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover zfcp updates for 2.6.35 merge window

James,

here is a series of zfcp patches for the 2.6.35 merge. The patches apply on top of the current scsi-misc tree.

--
Christof

#1 lore raw

PATCH 1/5 zfcp: Report scatter-gather limits to SCSI and block layer

From: Christof Schmitt <[email protected]>

Instead of dealing with large segments in the scatter-gather lists in zfcp_qdio.c, report the limits to the upper layers. With these limits in place, the code for mapping large data blocks to multiple sbales can be removed.

---

 drivers/s390/scsi/zfcp_aux.c  |    4 +++
 drivers/s390/scsi/zfcp_def.h  |    1 
 drivers/s390/scsi/zfcp_qdio.c |   45 ++++++++++--------------------------------
 drivers/s390/scsi/zfcp_qdio.h |    2 +
 drivers/s390/scsi/zfcp_scsi.c |    1 
 5 files changed, 19 insertions(+), 34 deletions(-)
drivers/s390/scsi/zfcp_aux.c +4 -0
@@ -545,6 +545,10 @@ struct zfcp_adapter *zfcp_adapter_enqueu
 			       &zfcp_sysfs_adapter_attrs))
 		goto failed;
 
+	/* report size limit per scatter-gather segment */
+	adapter->dma_parms.max_segment_size = ZFCP_QDIO_SBALE_LEN;
+	adapter->ccw_device->dev.dma_parms = &adapter->dma_parms;
+
 	if (!zfcp_adapter_scsi_register(adapter))
 		return adapter;
 
drivers/s390/scsi/zfcp_def.h +1 -0
@@ -205,6 +205,7 @@ struct zfcp_adapter {
 	struct work_struct	scan_work;
 	struct service_level	service_level;
 	struct workqueue_struct	*work_queue;
+	struct device_dma_parameters dma_parms;
 };
 
 struct zfcp_port {
drivers/s390/scsi/zfcp_qdio.c +11 -34

63 lines not on this page · raw message

drivers/s390/scsi/zfcp_qdio.h +2 -0
@@ -11,6 +11,8 @@
 
 #include <asm/qdio.h>
 
+#define ZFCP_QDIO_SBALE_LEN	PAGE_SIZE
+
 /**
  * struct zfcp_qdio_queue - qdio queue buffer, zfcp index and free count
  * @sbal: qdio buffers
drivers/s390/scsi/zfcp_scsi.c +1 -0
@@ -682,6 +682,7 @@ struct zfcp_data zfcp_data = {
 		.use_clustering		 = 1,
 		.sdev_attrs		 = zfcp_sysfs_sdev_attrs,
 		.max_sectors		 = (ZFCP_MAX_SBALES_PER_REQ * 8),
+		.dma_boundary		 = ZFCP_QDIO_SBALE_LEN - 1,
 		.shost_attrs		 = zfcp_sysfs_shost_attrs,
 	},
 };
#2 lore raw

PATCH 2/5 zfcp: Move sbale handling to zfcp_qdio files

In reply to Christof Schmitt

From: Christof Schmitt <[email protected]>

Move the code accessing the qdio sbales and zfcp_qdio_req struct to the zfcp_qdio files and provide helper functions for accessing the qdio related parts.

---

 drivers/s390/scsi/zfcp_def.h  |   17 ---
 drivers/s390/scsi/zfcp_ext.h  |    5 -
 drivers/s390/scsi/zfcp_fsf.c  |  180 +++++++++++++++---------------------------
 drivers/s390/scsi/zfcp_fsf.h  |    9 +-
 drivers/s390/scsi/zfcp_qdio.c |   25 ++---
 drivers/s390/scsi/zfcp_qdio.h |  102 +++++++++++++++++++++++
 drivers/s390/scsi/zfcp_scsi.c |    4 
 7 files changed, 191 insertions(+), 151 deletions(-)
drivers/s390/scsi/zfcp_def.h +0 -17
@@ -44,23 +44,6 @@ struct zfcp_reqlist;
 /********************* SCSI SPECIFIC DEFINES *********************************/
 #define ZFCP_SCSI_ER_TIMEOUT                    (10*HZ)
 
-/********************* CIO/QDIO SPECIFIC DEFINES *****************************/
-
-/* DMQ bug workaround: don't use last SBALE */
-#define ZFCP_MAX_SBALES_PER_SBAL	(QDIO_MAX_ELEMENTS_PER_BUFFER - 1)
-
-/* index of last SBALE (with respect to DMQ bug workaround) */
-#define ZFCP_LAST_SBALE_PER_SBAL	(ZFCP_MAX_SBALES_PER_SBAL - 1)
-
-/* max. number of (data buffer) SBALEs in largest SBAL chain */
-#define ZFCP_MAX_SBALES_PER_REQ		\
-	(FSF_MAX_SBALS_PER_REQ * ZFCP_MAX_SBALES_PER_SBAL - 2)
-        /* request ID + QTCB in SBALE 0 + 1 of first SBAL in chain */
-
-#define ZFCP_MAX_SECTORS (ZFCP_MAX_SBALES_PER_REQ * 8)
-        /* max. number of (data buffer) SBALEs in largest SBAL chain
-           multiplied with number of sectors per 4k block */
-
 /********************* FSF SPECIFIC DEFINES *********************************/
 
 /* ATTENTION: value must not be used by hardware */
drivers/s390/scsi/zfcp_ext.h +2 -3
@@ -3,7 +3,7 @@
  *
  * External function declarations.
  *
- * Copyright IBM Corporation 2002, 2009
+ * Copyright IBM Corporation 2002, 2010
  */
 
 #ifndef ZFCP_EXT_H
@@ -144,8 +144,7 @@ extern void zfcp_fsf_reqid_check(struct 
 extern int zfcp_qdio_setup(struct zfcp_adapter *);
 extern void zfcp_qdio_destroy(struct zfcp_qdio *);
 extern int zfcp_qdio_send(struct zfcp_qdio *, struct zfcp_qdio_req *);
-extern int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *,
-				   struct zfcp_qdio_req *, unsigned long,
+extern int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *, struct zfcp_qdio_req *,
 				   struct scatterlist *, int);
 extern int zfcp_qdio_open(struct zfcp_qdio *);
 extern void zfcp_qdio_close(struct zfcp_qdio *);
drivers/s390/scsi/zfcp_fsf.c +67 -113

564 lines not on this page · raw message

drivers/s390/scsi/zfcp_fsf.h +7 -2
@@ -3,7 +3,7 @@
  *
  * Interface to the FSF support functions.
  *
- * Copyright IBM Corporation 2002, 2009
+ * Copyright IBM Corporation 2002, 2010
  */
 
 #ifndef FSF_H
@@ -152,7 +152,12 @@
 #define FSF_CLASS_3				0x00000003
 
 /* SBAL chaining */
-#define FSF_MAX_SBALS_PER_REQ			36
+#define ZFCP_FSF_MAX_SBALS_PER_REQ		36
+
+/* max. number of (data buffer) SBALEs in largest SBAL chain
+ * request ID + QTCB in SBALE 0 + 1 of first SBAL in chain   */
+#define ZFCP_FSF_MAX_SBALES_PER_REQ	\
+	(ZFCP_FSF_MAX_SBALS_PER_REQ * ZFCP_QDIO_MAX_SBALES_PER_SBAL - 2)
 
 /* logging space behind QTCB */
 #define FSF_QTCB_LOG_SIZE			1024
drivers/s390/scsi/zfcp_qdio.c +11 -14
@@ -3,7 +3,7 @@
  *
  * Setup and helper functions to access QDIO.
  *
- * Copyright IBM Corporation 2002, 2009
+ * Copyright IBM Corporation 2002, 2010
  */
 
 #define KMSG_COMPONENT "zfcp"
@@ -151,8 +151,7 @@ static void zfcp_qdio_sbal_limit(struct 
 }
 
 static struct qdio_buffer_element *
-zfcp_qdio_sbal_chain(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
-		     unsigned long sbtype)
+zfcp_qdio_sbal_chain(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
 {
 	struct qdio_buffer_element *sbale;
 
@@ -180,17 +179,16 @@ zfcp_qdio_sbal_chain(struct zfcp_qdio *q
 
 	/* set storage-block type for new SBAL */
 	sbale = zfcp_qdio_sbale_curr(qdio, q_req);
-	sbale->flags |= sbtype;
+	sbale->flags |= q_req->sbtype;
 
 	return sbale;
 }
 
 static struct qdio_buffer_element *
-zfcp_qdio_sbale_next(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
-		     unsigned int sbtype)
+zfcp_qdio_sbale_next(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
 {
-	if (q_req->sbale_curr == ZFCP_LAST_SBALE_PER_SBAL)
-		return zfcp_qdio_sbal_chain(qdio, q_req, sbtype);
+	if (q_req->sbale_curr == ZFCP_QDIO_LAST_SBALE_PER_SBAL)
+		return zfcp_qdio_sbal_chain(qdio, q_req);
 	q_req->sbale_curr++;
 	return zfcp_qdio_sbale_curr(qdio, q_req);
 }
@@ -208,15 +206,14 @@ static void zfcp_qdio_undo_sbals(struct 
 
 /**
  * zfcp_qdio_sbals_from_sg - fill SBALs from scatter-gather list
- * @fsf_req: request to be processed
- * @sbtype: SBALE flags
+ * @qdio: pointer to struct zfcp_qdio
+ * @q_req: pointer to struct zfcp_qdio_req
  * @sg: scatter-gather list
  * @max_sbals: upper bound for number of SBALs to be used
  * Returns: number of bytes, or error (negativ)
  */
 int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
-			    unsigned long sbtype, struct scatterlist *sg,
-			    int max_sbals)
+			    struct scatterlist *sg, int max_sbals)
 {
 	struct qdio_buffer_element *sbale;
 	int bytes = 0;
@@ -226,10 +223,10 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_
 
 	/* set storage-block type for this request */
 	sbale = zfcp_qdio_sbale_req(qdio, q_req);
-	sbale->flags |= sbtype;
+	sbale->flags |= q_req->sbtype;
 
 	for (; sg; sg = sg_next(sg)) {
-		sbale = zfcp_qdio_sbale_next(qdio, q_req, sbtype);
+		sbale = zfcp_qdio_sbale_next(qdio, q_req);
 		if (!sbale) {
 			atomic_inc(&qdio->req_q_full);
 			zfcp_qdio_undo_sbals(qdio, q_req);
drivers/s390/scsi/zfcp_qdio.h +102 -0

124 lines not on this page · raw message

drivers/s390/scsi/zfcp_scsi.c +2 -2
@@ -677,11 +677,11 @@ struct zfcp_data zfcp_data = {
 		.eh_host_reset_handler	 = zfcp_scsi_eh_host_reset_handler,
 		.can_queue		 = 4096,
 		.this_id		 = -1,
-		.sg_tablesize		 = ZFCP_MAX_SBALES_PER_REQ,
+		.sg_tablesize		 = ZFCP_FSF_MAX_SBALES_PER_REQ,
 		.cmd_per_lun		 = 1,
 		.use_clustering		 = 1,
 		.sdev_attrs		 = zfcp_sysfs_sdev_attrs,
-		.max_sectors		 = (ZFCP_MAX_SBALES_PER_REQ * 8),
+		.max_sectors		 = (ZFCP_FSF_MAX_SBALES_PER_REQ * 8),
 		.dma_boundary		 = ZFCP_QDIO_SBALE_LEN - 1,
 		.shost_attrs		 = zfcp_sysfs_shost_attrs,
 	},
#3 lore raw

PATCH 3/5 zfcp: Move sbal_get function to zfcp_qdio.c

In reply to Christof Schmitt

From: Christof Schmitt <[email protected]>

Waiting for a free sbal is a operation on the qdio queue. Move the code implementing the wait to zfcp_qdio.c and rename the functions accordingly.

---

 drivers/s390/scsi/zfcp_ext.h  |    1 
 drivers/s390/scsi/zfcp_fsf.c  |   65 ++++++++++--------------------------------
 drivers/s390/scsi/zfcp_qdio.c |   40 +++++++++++++++++++++++++
 3 files changed, 58 insertions(+), 48 deletions(-)
drivers/s390/scsi/zfcp_ext.h +1 -0
@@ -143,6 +143,7 @@ extern void zfcp_fsf_reqid_check(struct 
 /* zfcp_qdio.c */
 extern int zfcp_qdio_setup(struct zfcp_adapter *);
 extern void zfcp_qdio_destroy(struct zfcp_qdio *);
+extern int zfcp_qdio_sbal_get(struct zfcp_qdio *);
 extern int zfcp_qdio_send(struct zfcp_qdio *, struct zfcp_qdio_req *);
 extern int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *, struct zfcp_qdio_req *,
 				   struct scatterlist *, int);
drivers/s390/scsi/zfcp_fsf.c +17 -48

173 lines not on this page · raw message

drivers/s390/scsi/zfcp_qdio.c +40 -0
@@ -246,6 +246,46 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_
 	return bytes;
 }
 
+static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio)
+{
+	struct zfcp_qdio_queue *req_q = &qdio->req_q;
+
+	spin_lock_bh(&qdio->req_q_lock);
+	if (atomic_read(&req_q->count))
+		return 1;
+	spin_unlock_bh(&qdio->req_q_lock);
+	return 0;
+}
+
+/**
+ * zfcp_qdio_sbal_get - get free sbal in request queue, wait if necessary
+ * @qdio: pointer to struct zfcp_qdio
+ *
+ * The req_q_lock must be held by the caller of this function, and
+ * this function may only be called from process context; it will
+ * sleep when waiting for a free sbal.
+ *
+ * Returns: 0 on success, -EIO if there is no free sbal after waiting.
+ */
+int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio)
+{
+	long ret;
+
+	spin_unlock_bh(&qdio->req_q_lock);
+	ret = wait_event_interruptible_timeout(qdio->req_q_wq,
+			       zfcp_qdio_sbal_check(qdio), 5 * HZ);
+	if (ret > 0)
+		return 0;
+	if (!ret) {
+		atomic_inc(&qdio->req_q_full);
+		/* assume hanging outbound queue, try queue recovery */
+		zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdsbg_1", NULL);
+	}
+
+	spin_lock_bh(&qdio->req_q_lock);
+	return -EIO;
+}
+
 /**
  * zfcp_qdio_send - set PCI flag in first SBALE and send req to QDIO
  * @qdio: pointer to struct zfcp_qdio
#4 lore raw

PATCH 4/5 zfcp: Use status_read_buf_num provided by FCP channel

In reply to Christof Schmitt

From: Christof Schmitt <[email protected]>

The FCP channel provides the number of status read buffers to issue. Use the provided number instead of the hardcoded number in zfcp.

---

 drivers/s390/scsi/zfcp_aux.c |    3 ++-
 drivers/s390/scsi/zfcp_def.h |    1 +
 drivers/s390/scsi/zfcp_erp.c |    2 +-
 drivers/s390/scsi/zfcp_fsf.c |    1 +
 drivers/s390/scsi/zfcp_fsf.h |    2 +-
 5 files changed, 6 insertions(+), 3 deletions(-)
drivers/s390/scsi/zfcp_aux.c +2 -1
@@ -425,7 +425,8 @@ int zfcp_status_read_refill(struct zfcp_
 {
 	while (atomic_read(&adapter->stat_miss) > 0)
 		if (zfcp_fsf_status_read(adapter->qdio)) {
-			if (atomic_read(&adapter->stat_miss) >= 16) {
+			if (atomic_read(&adapter->stat_miss) >=
+			    adapter->stat_read_buf_num) {
 				zfcp_erp_adapter_reopen(adapter, 0, "axsref1",
 							NULL);
 				return 1;
drivers/s390/scsi/zfcp_def.h +1 -0
@@ -164,6 +164,7 @@ struct zfcp_adapter {
 						      stack abort/command
 						      completion races */
 	atomic_t		stat_miss;	   /* # missing status reads*/
+	unsigned int		stat_read_buf_num;
 	struct work_struct	stat_work;
 	atomic_t		status;	           /* status of this adapter */
 	struct list_head	erp_ready_head;	   /* error recovery for this
drivers/s390/scsi/zfcp_erp.c +1 -1
@@ -714,7 +714,7 @@ static int zfcp_erp_adapter_strategy_ope
 	if (zfcp_erp_adapter_strategy_open_fsf_xport(act) == ZFCP_ERP_FAILED)
 		return ZFCP_ERP_FAILED;
 
-	atomic_set(&act->adapter->stat_miss, 16);
+	atomic_set(&act->adapter->stat_miss, act->adapter->stat_read_buf_num);
 	if (zfcp_status_read_refill(act->adapter))
 		return ZFCP_ERP_FAILED;
 
drivers/s390/scsi/zfcp_fsf.c +1 -0
@@ -496,6 +496,7 @@ static int zfcp_fsf_exchange_config_eval
 
 	adapter->hydra_version = bottom->adapter_type;
 	adapter->timer_ticks = bottom->timer_interval;
+	adapter->stat_read_buf_num = max(bottom->status_read_buf_num, (u16)16);
 
 	if (fc_host_permanent_port_name(shost) == -1)
 		fc_host_permanent_port_name(shost) = fc_host_port_name(shost);
drivers/s390/scsi/zfcp_fsf.h +1 -1
@@ -366,7 +366,7 @@ struct fsf_qtcb_bottom_config {
 	u32 adapter_type;
 	u8 res0;
 	u8 peer_d_id[3];
-	u8 res1[2];
+	u16 status_read_buf_num;
 	u16 timer_interval;
 	u8 res2[9];
 	u8 s_id[3];
#5 lore raw

PATCH 5/5 zfcp: Zero memory for gpn_ft and adisc requests

In reply to Christof Schmitt

From: Christof Schmitt <[email protected]>

With debug kernels, the memory allocated with kmem_cache_alloc might be initialized with the poison values 6b and a5. Use kmem_cache_zalloc instead of kmem_cache_alloc to get zeroed memory and not send invalid requests.

---
 drivers/s390/scsi/zfcp_fc.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/s390/scsi/zfcp_fc.c +2 -2
@@ -400,7 +400,7 @@ static int zfcp_fc_adisc(struct zfcp_por
 	struct zfcp_adapter *adapter = port->adapter;
 	int ret;
 
-	adisc = kmem_cache_alloc(zfcp_data.adisc_cache, GFP_ATOMIC);
+	adisc = kmem_cache_zalloc(zfcp_data.adisc_cache, GFP_ATOMIC);
 	if (!adisc)
 		return -ENOMEM;
 
@@ -493,7 +493,7 @@ static struct zfcp_fc_gpn_ft *zfcp_alloc
 	if (!gpn_ft)
 		return NULL;
 
-	req = kmem_cache_alloc(zfcp_data.gpn_ft_cache, GFP_KERNEL);
+	req = kmem_cache_zalloc(zfcp_data.gpn_ft_cache, GFP_KERNEL);
 	if (!req) {
 		kfree(gpn_ft);
 		gpn_ft = NULL;