xref: /openbmc/linux/drivers/s390/scsi/zfcp_qdio.c (revision 5156934bd62098cb80eeaabb77e9949c900e7092)
11da177e4SLinus Torvalds /*
200bab910SSwen Schillig  * zfcp device driver
31da177e4SLinus Torvalds  *
400bab910SSwen Schillig  * Setup and helper functions to access QDIO.
51da177e4SLinus Torvalds  *
6a53c8fabSHeiko Carstens  * Copyright IBM Corp. 2002, 2010
71da177e4SLinus Torvalds  */
81da177e4SLinus Torvalds 
9ecf39d42SChristof Schmitt #define KMSG_COMPONENT "zfcp"
10ecf39d42SChristof Schmitt #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
11ecf39d42SChristof Schmitt 
125a0e3ad6STejun Heo #include <linux/slab.h>
133a4c5d59SHeiko Carstens #include <linux/module.h>
141da177e4SLinus Torvalds #include "zfcp_ext.h"
1534c2b712SChristof Schmitt #include "zfcp_qdio.h"
161da177e4SLinus Torvalds 
17*5156934bSBenjamin Block static bool enable_multibuffer = true;
1886a9668aSSwen Schillig module_param_named(datarouter, enable_multibuffer, bool, 0400);
19909ee499SSteffen Maier MODULE_PARM_DESC(datarouter, "Enable hardware data router support (default on)");
2086a9668aSSwen Schillig 
21339f4f4eSChristof Schmitt static void zfcp_qdio_handler_error(struct zfcp_qdio *qdio, char *id,
22339f4f4eSChristof Schmitt 				    unsigned int qdio_err)
2300bab910SSwen Schillig {
24564e1c86SSwen Schillig 	struct zfcp_adapter *adapter = qdio->adapter;
25564e1c86SSwen Schillig 
26ff3b24faSChristof Schmitt 	dev_warn(&adapter->ccw_device->dev, "A QDIO problem occurred\n");
2700bab910SSwen Schillig 
2886a9668aSSwen Schillig 	if (qdio_err & QDIO_ERROR_SLSB_STATE) {
29339f4f4eSChristof Schmitt 		zfcp_qdio_siosl(adapter);
3086a9668aSSwen Schillig 		zfcp_erp_adapter_shutdown(adapter, 0, id);
3186a9668aSSwen Schillig 		return;
3286a9668aSSwen Schillig 	}
3300bab910SSwen Schillig 	zfcp_erp_adapter_reopen(adapter,
3400bab910SSwen Schillig 				ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
35ea4a3a6aSSwen Schillig 				ZFCP_STATUS_COMMON_ERP_FAILED, id);
3600bab910SSwen Schillig }
3700bab910SSwen Schillig 
385d4e2262SChristof Schmitt static void zfcp_qdio_zero_sbals(struct qdio_buffer *sbal[], int first, int cnt)
395d4e2262SChristof Schmitt {
405d4e2262SChristof Schmitt 	int i, sbal_idx;
415d4e2262SChristof Schmitt 
425d4e2262SChristof Schmitt 	for (i = first; i < first + cnt; i++) {
435d4e2262SChristof Schmitt 		sbal_idx = i % QDIO_MAX_BUFFERS_PER_Q;
445d4e2262SChristof Schmitt 		memset(sbal[sbal_idx], 0, sizeof(struct qdio_buffer));
455d4e2262SChristof Schmitt 	}
465d4e2262SChristof Schmitt }
475d4e2262SChristof Schmitt 
4894506fd1SMartin Peschke /* this needs to be called prior to updating the queue fill level */
4941e05a12SHeiko Carstens static inline void zfcp_qdio_account(struct zfcp_qdio *qdio)
5094506fd1SMartin Peschke {
5141e05a12SHeiko Carstens 	unsigned long long now, span;
52706eca49SSwen Schillig 	int used;
5394506fd1SMartin Peschke 
541aae0560SHeiko Carstens 	now = get_tod_clock_monotonic();
5541e05a12SHeiko Carstens 	span = (now - qdio->req_q_time) >> 12;
56706eca49SSwen Schillig 	used = QDIO_MAX_BUFFERS_PER_Q - atomic_read(&qdio->req_q_free);
57564e1c86SSwen Schillig 	qdio->req_q_util += used * span;
58564e1c86SSwen Schillig 	qdio->req_q_time = now;
5994506fd1SMartin Peschke }
6094506fd1SMartin Peschke 
61779e6e1cSJan Glauber static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err,
62706eca49SSwen Schillig 			      int queue_no, int idx, int count,
6300bab910SSwen Schillig 			      unsigned long parm)
6400bab910SSwen Schillig {
65564e1c86SSwen Schillig 	struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm;
6600bab910SSwen Schillig 
67779e6e1cSJan Glauber 	if (unlikely(qdio_err)) {
68339f4f4eSChristof Schmitt 		zfcp_qdio_handler_error(qdio, "qdireq1", qdio_err);
6900bab910SSwen Schillig 		return;
7000bab910SSwen Schillig 	}
7100bab910SSwen Schillig 
7200bab910SSwen Schillig 	/* cleanup all SBALs being program-owned now */
73706eca49SSwen Schillig 	zfcp_qdio_zero_sbals(qdio->req_q, idx, count);
7400bab910SSwen Schillig 
7544a24cb3SChristof Schmitt 	spin_lock_irq(&qdio->stat_lock);
76564e1c86SSwen Schillig 	zfcp_qdio_account(qdio);
7744a24cb3SChristof Schmitt 	spin_unlock_irq(&qdio->stat_lock);
78706eca49SSwen Schillig 	atomic_add(count, &qdio->req_q_free);
79564e1c86SSwen Schillig 	wake_up(&qdio->req_q_wq);
8000bab910SSwen Schillig }
8100bab910SSwen Schillig 
82779e6e1cSJan Glauber static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err,
83706eca49SSwen Schillig 			       int queue_no, int idx, int count,
8400bab910SSwen Schillig 			       unsigned long parm)
8500bab910SSwen Schillig {
86564e1c86SSwen Schillig 	struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm;
8786a9668aSSwen Schillig 	struct zfcp_adapter *adapter = qdio->adapter;
8886a9668aSSwen Schillig 	int sbal_no, sbal_idx;
8901e60527SSteffen Maier 
9001e60527SSteffen Maier 	if (unlikely(qdio_err)) {
9101e60527SSteffen Maier 		if (zfcp_adapter_multi_buffer_active(adapter)) {
9286a9668aSSwen Schillig 			void *pl[ZFCP_QDIO_MAX_SBALS_PER_REQ + 1];
9301e60527SSteffen Maier 			struct qdio_buffer_element *sbale;
9486a9668aSSwen Schillig 			u64 req_id;
9586a9668aSSwen Schillig 			u8 scount;
9600bab910SSwen Schillig 
9701e60527SSteffen Maier 			memset(pl, 0,
9801e60527SSteffen Maier 			       ZFCP_QDIO_MAX_SBALS_PER_REQ * sizeof(void *));
9986a9668aSSwen Schillig 			sbale = qdio->res_q[idx]->element;
10086a9668aSSwen Schillig 			req_id = (u64) sbale->addr;
10101e60527SSteffen Maier 			scount = min(sbale->scount + 1,
10201e60527SSteffen Maier 				     ZFCP_QDIO_MAX_SBALS_PER_REQ + 1);
10301e60527SSteffen Maier 				     /* incl. signaling SBAL */
10486a9668aSSwen Schillig 
10586a9668aSSwen Schillig 			for (sbal_no = 0; sbal_no < scount; sbal_no++) {
10686a9668aSSwen Schillig 				sbal_idx = (idx + sbal_no) %
10786a9668aSSwen Schillig 					QDIO_MAX_BUFFERS_PER_Q;
10886a9668aSSwen Schillig 				pl[sbal_no] = qdio->res_q[sbal_idx];
10986a9668aSSwen Schillig 			}
11086a9668aSSwen Schillig 			zfcp_dbf_hba_def_err(adapter, req_id, scount, pl);
11186a9668aSSwen Schillig 		}
112339f4f4eSChristof Schmitt 		zfcp_qdio_handler_error(qdio, "qdires1", qdio_err);
11300bab910SSwen Schillig 		return;
11400bab910SSwen Schillig 	}
11500bab910SSwen Schillig 
1161da177e4SLinus Torvalds 	/*
1171da177e4SLinus Torvalds 	 * go through all SBALs from input queue currently
1181da177e4SLinus Torvalds 	 * returned by QDIO layer
1191da177e4SLinus Torvalds 	 */
12000bab910SSwen Schillig 	for (sbal_no = 0; sbal_no < count; sbal_no++) {
121706eca49SSwen Schillig 		sbal_idx = (idx + sbal_no) % QDIO_MAX_BUFFERS_PER_Q;
1221da177e4SLinus Torvalds 		/* go through all SBALEs of SBAL */
123564e1c86SSwen Schillig 		zfcp_fsf_reqid_check(qdio, sbal_idx);
1241da177e4SLinus Torvalds 	}
1251da177e4SLinus Torvalds 
1261da177e4SLinus Torvalds 	/*
127706eca49SSwen Schillig 	 * put SBALs back to response queue
1281da177e4SLinus Torvalds 	 */
129706eca49SSwen Schillig 	if (do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT, 0, idx, count))
130ea4a3a6aSSwen Schillig 		zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdires2");
1311da177e4SLinus Torvalds }
1321da177e4SLinus Torvalds 
13344cc76f2SSwen Schillig static struct qdio_buffer_element *
1341674b405SChristof Schmitt zfcp_qdio_sbal_chain(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
1351da177e4SLinus Torvalds {
13644cc76f2SSwen Schillig 	struct qdio_buffer_element *sbale;
1371da177e4SLinus Torvalds 
1381da177e4SLinus Torvalds 	/* set last entry flag in current SBALE of current SBAL */
139564e1c86SSwen Schillig 	sbale = zfcp_qdio_sbale_curr(qdio, q_req);
1403ec90878SJan Glauber 	sbale->eflags |= SBAL_EFLAGS_LAST_ENTRY;
1411da177e4SLinus Torvalds 
1421da177e4SLinus Torvalds 	/* don't exceed last allowed SBAL */
14342428f74SSwen Schillig 	if (q_req->sbal_last == q_req->sbal_limit)
1441da177e4SLinus Torvalds 		return NULL;
1451da177e4SLinus Torvalds 
1461da177e4SLinus Torvalds 	/* set chaining flag in first SBALE of current SBAL */
147564e1c86SSwen Schillig 	sbale = zfcp_qdio_sbale_req(qdio, q_req);
1483ec90878SJan Glauber 	sbale->sflags |= SBAL_SFLAGS0_MORE_SBALS;
1491da177e4SLinus Torvalds 
1501da177e4SLinus Torvalds 	/* calculate index of next SBAL */
15142428f74SSwen Schillig 	q_req->sbal_last++;
15242428f74SSwen Schillig 	q_req->sbal_last %= QDIO_MAX_BUFFERS_PER_Q;
1531da177e4SLinus Torvalds 
1541da177e4SLinus Torvalds 	/* keep this requests number of SBALs up-to-date */
15542428f74SSwen Schillig 	q_req->sbal_number++;
15601b04759SSwen Schillig 	BUG_ON(q_req->sbal_number > ZFCP_QDIO_MAX_SBALS_PER_REQ);
1571da177e4SLinus Torvalds 
1581da177e4SLinus Torvalds 	/* start at first SBALE of new SBAL */
15942428f74SSwen Schillig 	q_req->sbale_curr = 0;
1601da177e4SLinus Torvalds 
1611da177e4SLinus Torvalds 	/* set storage-block type for new SBAL */
162564e1c86SSwen Schillig 	sbale = zfcp_qdio_sbale_curr(qdio, q_req);
1633ec90878SJan Glauber 	sbale->sflags |= q_req->sbtype;
1641da177e4SLinus Torvalds 
1651da177e4SLinus Torvalds 	return sbale;
1661da177e4SLinus Torvalds }
1671da177e4SLinus Torvalds 
16844cc76f2SSwen Schillig static struct qdio_buffer_element *
1691674b405SChristof Schmitt zfcp_qdio_sbale_next(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
1701da177e4SLinus Torvalds {
17186a9668aSSwen Schillig 	if (q_req->sbale_curr == qdio->max_sbale_per_sbal - 1)
1721674b405SChristof Schmitt 		return zfcp_qdio_sbal_chain(qdio, q_req);
17342428f74SSwen Schillig 	q_req->sbale_curr++;
174564e1c86SSwen Schillig 	return zfcp_qdio_sbale_curr(qdio, q_req);
1751da177e4SLinus Torvalds }
1761da177e4SLinus Torvalds 
1771da177e4SLinus Torvalds /**
1781da177e4SLinus Torvalds  * zfcp_qdio_sbals_from_sg - fill SBALs from scatter-gather list
1791674b405SChristof Schmitt  * @qdio: pointer to struct zfcp_qdio
1801674b405SChristof Schmitt  * @q_req: pointer to struct zfcp_qdio_req
1811da177e4SLinus Torvalds  * @sg: scatter-gather list
1821da177e4SLinus Torvalds  * @max_sbals: upper bound for number of SBALs to be used
18386a9668aSSwen Schillig  * Returns: zero or -EINVAL on error
1841da177e4SLinus Torvalds  */
18534c2b712SChristof Schmitt int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
18601b04759SSwen Schillig 			    struct scatterlist *sg)
1871da177e4SLinus Torvalds {
18844cc76f2SSwen Schillig 	struct qdio_buffer_element *sbale;
1891da177e4SLinus Torvalds 
19000bab910SSwen Schillig 	/* set storage-block type for this request */
191564e1c86SSwen Schillig 	sbale = zfcp_qdio_sbale_req(qdio, q_req);
1923ec90878SJan Glauber 	sbale->sflags |= q_req->sbtype;
1931da177e4SLinus Torvalds 
19400bab910SSwen Schillig 	for (; sg; sg = sg_next(sg)) {
1951674b405SChristof Schmitt 		sbale = zfcp_qdio_sbale_next(qdio, q_req);
19668322984SChristof Schmitt 		if (!sbale) {
19768322984SChristof Schmitt 			atomic_inc(&qdio->req_q_full);
198706eca49SSwen Schillig 			zfcp_qdio_zero_sbals(qdio->req_q, q_req->sbal_first,
199706eca49SSwen Schillig 					     q_req->sbal_number);
20068322984SChristof Schmitt 			return -EINVAL;
20168322984SChristof Schmitt 		}
20268322984SChristof Schmitt 		sbale->addr = sg_virt(sg);
20368322984SChristof Schmitt 		sbale->length = sg->length;
2041da177e4SLinus Torvalds 	}
20586a9668aSSwen Schillig 	return 0;
2061da177e4SLinus Torvalds }
2071da177e4SLinus Torvalds 
2086b9e1520SChristof Schmitt static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio)
2096b9e1520SChristof Schmitt {
210706eca49SSwen Schillig 	if (atomic_read(&qdio->req_q_free) ||
211c2af7545SChristof Schmitt 	    !(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
2126b9e1520SChristof Schmitt 		return 1;
2136b9e1520SChristof Schmitt 	return 0;
2146b9e1520SChristof Schmitt }
2156b9e1520SChristof Schmitt 
2166b9e1520SChristof Schmitt /**
2176b9e1520SChristof Schmitt  * zfcp_qdio_sbal_get - get free sbal in request queue, wait if necessary
2186b9e1520SChristof Schmitt  * @qdio: pointer to struct zfcp_qdio
2196b9e1520SChristof Schmitt  *
2206b9e1520SChristof Schmitt  * The req_q_lock must be held by the caller of this function, and
2216b9e1520SChristof Schmitt  * this function may only be called from process context; it will
2226b9e1520SChristof Schmitt  * sleep when waiting for a free sbal.
2236b9e1520SChristof Schmitt  *
2246b9e1520SChristof Schmitt  * Returns: 0 on success, -EIO if there is no free sbal after waiting.
2256b9e1520SChristof Schmitt  */
2266b9e1520SChristof Schmitt int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio)
2276b9e1520SChristof Schmitt {
2286b9e1520SChristof Schmitt 	long ret;
2296b9e1520SChristof Schmitt 
230d79ff142SMartin Peschke 	ret = wait_event_interruptible_lock_irq_timeout(qdio->req_q_wq,
231d79ff142SMartin Peschke 		       zfcp_qdio_sbal_check(qdio), qdio->req_q_lock, 5 * HZ);
232c2af7545SChristof Schmitt 
233c2af7545SChristof Schmitt 	if (!(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
234c2af7545SChristof Schmitt 		return -EIO;
235c2af7545SChristof Schmitt 
2366b9e1520SChristof Schmitt 	if (ret > 0)
2376b9e1520SChristof Schmitt 		return 0;
238c2af7545SChristof Schmitt 
2396b9e1520SChristof Schmitt 	if (!ret) {
2406b9e1520SChristof Schmitt 		atomic_inc(&qdio->req_q_full);
2416b9e1520SChristof Schmitt 		/* assume hanging outbound queue, try queue recovery */
242ea4a3a6aSSwen Schillig 		zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdsbg_1");
2436b9e1520SChristof Schmitt 	}
2446b9e1520SChristof Schmitt 
2456b9e1520SChristof Schmitt 	return -EIO;
2466b9e1520SChristof Schmitt }
2476b9e1520SChristof Schmitt 
2481da177e4SLinus Torvalds /**
24900bab910SSwen Schillig  * zfcp_qdio_send - set PCI flag in first SBALE and send req to QDIO
250564e1c86SSwen Schillig  * @qdio: pointer to struct zfcp_qdio
25134c2b712SChristof Schmitt  * @q_req: pointer to struct zfcp_qdio_req
25200bab910SSwen Schillig  * Returns: 0 on success, error otherwise
2531da177e4SLinus Torvalds  */
25434c2b712SChristof Schmitt int zfcp_qdio_send(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
2551da177e4SLinus Torvalds {
25621ddaa53SChristof Schmitt 	int retval;
257706eca49SSwen Schillig 	u8 sbal_number = q_req->sbal_number;
25800bab910SSwen Schillig 
25944a24cb3SChristof Schmitt 	spin_lock(&qdio->stat_lock);
260564e1c86SSwen Schillig 	zfcp_qdio_account(qdio);
26144a24cb3SChristof Schmitt 	spin_unlock(&qdio->stat_lock);
26294506fd1SMartin Peschke 
263706eca49SSwen Schillig 	retval = do_QDIO(qdio->adapter->ccw_device, QDIO_FLAG_SYNC_OUTPUT, 0,
264706eca49SSwen Schillig 			 q_req->sbal_first, sbal_number);
265706eca49SSwen Schillig 
26600bab910SSwen Schillig 	if (unlikely(retval)) {
267706eca49SSwen Schillig 		zfcp_qdio_zero_sbals(qdio->req_q, q_req->sbal_first,
268706eca49SSwen Schillig 				     sbal_number);
26900bab910SSwen Schillig 		return retval;
2701da177e4SLinus Torvalds 	}
2711da177e4SLinus Torvalds 
27200bab910SSwen Schillig 	/* account for transferred buffers */
273706eca49SSwen Schillig 	atomic_sub(sbal_number, &qdio->req_q_free);
274706eca49SSwen Schillig 	qdio->req_q_idx += sbal_number;
275706eca49SSwen Schillig 	qdio->req_q_idx %= QDIO_MAX_BUFFERS_PER_Q;
276706eca49SSwen Schillig 
27700bab910SSwen Schillig 	return 0;
27800bab910SSwen Schillig }
27900bab910SSwen Schillig 
280564e1c86SSwen Schillig 
281564e1c86SSwen Schillig static void zfcp_qdio_setup_init_data(struct qdio_initialize *id,
282564e1c86SSwen Schillig 				      struct zfcp_qdio *qdio)
283564e1c86SSwen Schillig {
284d36deae7SJan Glauber 	memset(id, 0, sizeof(*id));
285564e1c86SSwen Schillig 	id->cdev = qdio->adapter->ccw_device;
286564e1c86SSwen Schillig 	id->q_format = QDIO_ZFCP_QFMT;
287564e1c86SSwen Schillig 	memcpy(id->adapter_name, dev_name(&id->cdev->dev), 8);
288564e1c86SSwen Schillig 	ASCEBC(id->adapter_name, 8);
289dcc18f48SChristof Schmitt 	id->qib_rflags = QIB_RFLAGS_ENABLE_DATA_DIV;
29086a9668aSSwen Schillig 	if (enable_multibuffer)
29186a9668aSSwen Schillig 		id->qdr_ac |= QDR_AC_MULTI_BUFFER_ENABLE;
292564e1c86SSwen Schillig 	id->no_input_qs = 1;
293564e1c86SSwen Schillig 	id->no_output_qs = 1;
294564e1c86SSwen Schillig 	id->input_handler = zfcp_qdio_int_resp;
295564e1c86SSwen Schillig 	id->output_handler = zfcp_qdio_int_req;
296564e1c86SSwen Schillig 	id->int_parm = (unsigned long) qdio;
297706eca49SSwen Schillig 	id->input_sbal_addr_array = (void **) (qdio->res_q);
298706eca49SSwen Schillig 	id->output_sbal_addr_array = (void **) (qdio->req_q);
2993d6c76ffSJan Glauber 	id->scan_threshold =
3003d6c76ffSJan Glauber 		QDIO_MAX_BUFFERS_PER_Q - ZFCP_QDIO_MAX_SBALS_PER_REQ * 2;
301564e1c86SSwen Schillig }
302dcc18f48SChristof Schmitt 
30300bab910SSwen Schillig /**
30400bab910SSwen Schillig  * zfcp_qdio_allocate - allocate queue memory and initialize QDIO data
30500bab910SSwen Schillig  * @adapter: pointer to struct zfcp_adapter
30600bab910SSwen Schillig  * Returns: -ENOMEM on memory allocation error or return value from
30700bab910SSwen Schillig  *          qdio_allocate
30800bab910SSwen Schillig  */
309d5a282a1SSwen Schillig static int zfcp_qdio_allocate(struct zfcp_qdio *qdio)
31000bab910SSwen Schillig {
311564e1c86SSwen Schillig 	struct qdio_initialize init_data;
312852eb1aaSSebastian Ott 	int ret;
31300bab910SSwen Schillig 
314852eb1aaSSebastian Ott 	ret = qdio_alloc_buffers(qdio->req_q, QDIO_MAX_BUFFERS_PER_Q);
315852eb1aaSSebastian Ott 	if (ret)
31600bab910SSwen Schillig 		return -ENOMEM;
31700bab910SSwen Schillig 
318852eb1aaSSebastian Ott 	ret = qdio_alloc_buffers(qdio->res_q, QDIO_MAX_BUFFERS_PER_Q);
319852eb1aaSSebastian Ott 	if (ret)
320852eb1aaSSebastian Ott 		goto free_req_q;
321852eb1aaSSebastian Ott 
322564e1c86SSwen Schillig 	zfcp_qdio_setup_init_data(&init_data, qdio);
3233d63d3b4SChristof Schmitt 	init_waitqueue_head(&qdio->req_q_wq);
32400bab910SSwen Schillig 
325852eb1aaSSebastian Ott 	ret = qdio_allocate(&init_data);
326852eb1aaSSebastian Ott 	if (ret)
327852eb1aaSSebastian Ott 		goto free_res_q;
328852eb1aaSSebastian Ott 
329852eb1aaSSebastian Ott 	return 0;
330852eb1aaSSebastian Ott 
331852eb1aaSSebastian Ott free_res_q:
332852eb1aaSSebastian Ott 	qdio_free_buffers(qdio->res_q, QDIO_MAX_BUFFERS_PER_Q);
333852eb1aaSSebastian Ott free_req_q:
334852eb1aaSSebastian Ott 	qdio_free_buffers(qdio->req_q, QDIO_MAX_BUFFERS_PER_Q);
335852eb1aaSSebastian Ott 	return ret;
33600bab910SSwen Schillig }
33700bab910SSwen Schillig 
33800bab910SSwen Schillig /**
33900bab910SSwen Schillig  * zfcp_close_qdio - close qdio queues for an adapter
340564e1c86SSwen Schillig  * @qdio: pointer to structure zfcp_qdio
34100bab910SSwen Schillig  */
342564e1c86SSwen Schillig void zfcp_qdio_close(struct zfcp_qdio *qdio)
34300bab910SSwen Schillig {
344706eca49SSwen Schillig 	struct zfcp_adapter *adapter = qdio->adapter;
345706eca49SSwen Schillig 	int idx, count;
34600bab910SSwen Schillig 
347706eca49SSwen Schillig 	if (!(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
34800bab910SSwen Schillig 		return;
34900bab910SSwen Schillig 
35000bab910SSwen Schillig 	/* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */
35144a24cb3SChristof Schmitt 	spin_lock_irq(&qdio->req_q_lock);
352805de8f4SPeter Zijlstra 	atomic_andnot(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
35344a24cb3SChristof Schmitt 	spin_unlock_irq(&qdio->req_q_lock);
35400bab910SSwen Schillig 
355c2af7545SChristof Schmitt 	wake_up(&qdio->req_q_wq);
356c2af7545SChristof Schmitt 
357706eca49SSwen Schillig 	qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR);
35800bab910SSwen Schillig 
35900bab910SSwen Schillig 	/* cleanup used outbound sbals */
360706eca49SSwen Schillig 	count = atomic_read(&qdio->req_q_free);
36100bab910SSwen Schillig 	if (count < QDIO_MAX_BUFFERS_PER_Q) {
362706eca49SSwen Schillig 		idx = (qdio->req_q_idx + count) % QDIO_MAX_BUFFERS_PER_Q;
36300bab910SSwen Schillig 		count = QDIO_MAX_BUFFERS_PER_Q - count;
364706eca49SSwen Schillig 		zfcp_qdio_zero_sbals(qdio->req_q, idx, count);
36500bab910SSwen Schillig 	}
366706eca49SSwen Schillig 	qdio->req_q_idx = 0;
367706eca49SSwen Schillig 	atomic_set(&qdio->req_q_free, 0);
36800bab910SSwen Schillig }
36900bab910SSwen Schillig 
37000bab910SSwen Schillig /**
37100bab910SSwen Schillig  * zfcp_qdio_open - prepare and initialize response queue
372564e1c86SSwen Schillig  * @qdio: pointer to struct zfcp_qdio
37300bab910SSwen Schillig  * Returns: 0 on success, otherwise -EIO
37400bab910SSwen Schillig  */
375564e1c86SSwen Schillig int zfcp_qdio_open(struct zfcp_qdio *qdio)
37600bab910SSwen Schillig {
37744cc76f2SSwen Schillig 	struct qdio_buffer_element *sbale;
378564e1c86SSwen Schillig 	struct qdio_initialize init_data;
379706eca49SSwen Schillig 	struct zfcp_adapter *adapter = qdio->adapter;
380706eca49SSwen Schillig 	struct ccw_device *cdev = adapter->ccw_device;
381dcc18f48SChristof Schmitt 	struct qdio_ssqd_desc ssqd;
38200bab910SSwen Schillig 	int cc;
38300bab910SSwen Schillig 
384706eca49SSwen Schillig 	if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)
38500bab910SSwen Schillig 		return -EIO;
38600bab910SSwen Schillig 
387805de8f4SPeter Zijlstra 	atomic_andnot(ZFCP_STATUS_ADAPTER_SIOSL_ISSUED,
388339f4f4eSChristof Schmitt 			  &qdio->adapter->status);
389339f4f4eSChristof Schmitt 
390564e1c86SSwen Schillig 	zfcp_qdio_setup_init_data(&init_data, qdio);
391564e1c86SSwen Schillig 
392564e1c86SSwen Schillig 	if (qdio_establish(&init_data))
393ff3b24faSChristof Schmitt 		goto failed_establish;
39400bab910SSwen Schillig 
395dcc18f48SChristof Schmitt 	if (qdio_get_ssqd_desc(init_data.cdev, &ssqd))
396dcc18f48SChristof Schmitt 		goto failed_qdio;
397dcc18f48SChristof Schmitt 
398dcc18f48SChristof Schmitt 	if (ssqd.qdioac2 & CHSC_AC2_DATA_DIV_ENABLED)
399805de8f4SPeter Zijlstra 		atomic_or(ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED,
400dcc18f48SChristof Schmitt 				&qdio->adapter->status);
401dcc18f48SChristof Schmitt 
40286a9668aSSwen Schillig 	if (ssqd.qdioac2 & CHSC_AC2_MULTI_BUFFER_ENABLED) {
403805de8f4SPeter Zijlstra 		atomic_or(ZFCP_STATUS_ADAPTER_MB_ACT, &adapter->status);
40486a9668aSSwen Schillig 		qdio->max_sbale_per_sbal = QDIO_MAX_ELEMENTS_PER_BUFFER;
40586a9668aSSwen Schillig 	} else {
406805de8f4SPeter Zijlstra 		atomic_andnot(ZFCP_STATUS_ADAPTER_MB_ACT, &adapter->status);
40786a9668aSSwen Schillig 		qdio->max_sbale_per_sbal = QDIO_MAX_ELEMENTS_PER_BUFFER - 1;
40886a9668aSSwen Schillig 	}
40986a9668aSSwen Schillig 
41086a9668aSSwen Schillig 	qdio->max_sbale_per_req =
41186a9668aSSwen Schillig 		ZFCP_QDIO_MAX_SBALS_PER_REQ * qdio->max_sbale_per_sbal
41286a9668aSSwen Schillig 		- 2;
413564e1c86SSwen Schillig 	if (qdio_activate(cdev))
41400bab910SSwen Schillig 		goto failed_qdio;
41500bab910SSwen Schillig 
41600bab910SSwen Schillig 	for (cc = 0; cc < QDIO_MAX_BUFFERS_PER_Q; cc++) {
417706eca49SSwen Schillig 		sbale = &(qdio->res_q[cc]->element[0]);
41800bab910SSwen Schillig 		sbale->length = 0;
4193ec90878SJan Glauber 		sbale->eflags = SBAL_EFLAGS_LAST_ENTRY;
4203ec90878SJan Glauber 		sbale->sflags = 0;
42100bab910SSwen Schillig 		sbale->addr = NULL;
42200bab910SSwen Schillig 	}
42300bab910SSwen Schillig 
424706eca49SSwen Schillig 	if (do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT, 0, 0, QDIO_MAX_BUFFERS_PER_Q))
42500bab910SSwen Schillig 		goto failed_qdio;
42600bab910SSwen Schillig 
42725985edcSLucas De Marchi 	/* set index of first available SBALS / number of available SBALS */
428706eca49SSwen Schillig 	qdio->req_q_idx = 0;
429706eca49SSwen Schillig 	atomic_set(&qdio->req_q_free, QDIO_MAX_BUFFERS_PER_Q);
430805de8f4SPeter Zijlstra 	atomic_or(ZFCP_STATUS_ADAPTER_QDIOUP, &qdio->adapter->status);
43100bab910SSwen Schillig 
43286a9668aSSwen Schillig 	if (adapter->scsi_host) {
43386a9668aSSwen Schillig 		adapter->scsi_host->sg_tablesize = qdio->max_sbale_per_req;
43486a9668aSSwen Schillig 		adapter->scsi_host->max_sectors = qdio->max_sbale_per_req * 8;
43586a9668aSSwen Schillig 	}
43686a9668aSSwen Schillig 
43700bab910SSwen Schillig 	return 0;
43800bab910SSwen Schillig 
43900bab910SSwen Schillig failed_qdio:
440564e1c86SSwen Schillig 	qdio_shutdown(cdev, QDIO_FLAG_CLEANUP_USING_CLEAR);
441ff3b24faSChristof Schmitt failed_establish:
442564e1c86SSwen Schillig 	dev_err(&cdev->dev,
443ff3b24faSChristof Schmitt 		"Setting up the QDIO connection to the FCP adapter failed\n");
44400bab910SSwen Schillig 	return -EIO;
44500bab910SSwen Schillig }
446d5a282a1SSwen Schillig 
447d5a282a1SSwen Schillig void zfcp_qdio_destroy(struct zfcp_qdio *qdio)
448d5a282a1SSwen Schillig {
449d5a282a1SSwen Schillig 	if (!qdio)
450d5a282a1SSwen Schillig 		return;
451d5a282a1SSwen Schillig 
452d5a282a1SSwen Schillig 	if (qdio->adapter->ccw_device)
453d5a282a1SSwen Schillig 		qdio_free(qdio->adapter->ccw_device);
454d5a282a1SSwen Schillig 
455852eb1aaSSebastian Ott 	qdio_free_buffers(qdio->req_q, QDIO_MAX_BUFFERS_PER_Q);
456852eb1aaSSebastian Ott 	qdio_free_buffers(qdio->res_q, QDIO_MAX_BUFFERS_PER_Q);
457d5a282a1SSwen Schillig 	kfree(qdio);
458d5a282a1SSwen Schillig }
459d5a282a1SSwen Schillig 
460d5a282a1SSwen Schillig int zfcp_qdio_setup(struct zfcp_adapter *adapter)
461d5a282a1SSwen Schillig {
462d5a282a1SSwen Schillig 	struct zfcp_qdio *qdio;
463d5a282a1SSwen Schillig 
464d5a282a1SSwen Schillig 	qdio = kzalloc(sizeof(struct zfcp_qdio), GFP_KERNEL);
465d5a282a1SSwen Schillig 	if (!qdio)
466d5a282a1SSwen Schillig 		return -ENOMEM;
467d5a282a1SSwen Schillig 
468d5a282a1SSwen Schillig 	qdio->adapter = adapter;
469d5a282a1SSwen Schillig 
470d5a282a1SSwen Schillig 	if (zfcp_qdio_allocate(qdio)) {
471852eb1aaSSebastian Ott 		kfree(qdio);
472d5a282a1SSwen Schillig 		return -ENOMEM;
473d5a282a1SSwen Schillig 	}
474d5a282a1SSwen Schillig 
475d5a282a1SSwen Schillig 	spin_lock_init(&qdio->req_q_lock);
476d5a282a1SSwen Schillig 	spin_lock_init(&qdio->stat_lock);
477d5a282a1SSwen Schillig 
478d5a282a1SSwen Schillig 	adapter->qdio = qdio;
479d5a282a1SSwen Schillig 	return 0;
480d5a282a1SSwen Schillig }
481d5a282a1SSwen Schillig 
482339f4f4eSChristof Schmitt /**
483339f4f4eSChristof Schmitt  * zfcp_qdio_siosl - Trigger logging in FCP channel
484339f4f4eSChristof Schmitt  * @adapter: The zfcp_adapter where to trigger logging
485339f4f4eSChristof Schmitt  *
486339f4f4eSChristof Schmitt  * Call the cio siosl function to trigger hardware logging.  This
487339f4f4eSChristof Schmitt  * wrapper function sets a flag to ensure hardware logging is only
488339f4f4eSChristof Schmitt  * triggered once before going through qdio shutdown.
489339f4f4eSChristof Schmitt  *
490339f4f4eSChristof Schmitt  * The triggers are always run from qdio tasklet context, so no
491339f4f4eSChristof Schmitt  * additional synchronization is necessary.
492339f4f4eSChristof Schmitt  */
493339f4f4eSChristof Schmitt void zfcp_qdio_siosl(struct zfcp_adapter *adapter)
494339f4f4eSChristof Schmitt {
495339f4f4eSChristof Schmitt 	int rc;
496339f4f4eSChristof Schmitt 
497339f4f4eSChristof Schmitt 	if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_SIOSL_ISSUED)
498339f4f4eSChristof Schmitt 		return;
499339f4f4eSChristof Schmitt 
500339f4f4eSChristof Schmitt 	rc = ccw_device_siosl(adapter->ccw_device);
501339f4f4eSChristof Schmitt 	if (!rc)
502805de8f4SPeter Zijlstra 		atomic_or(ZFCP_STATUS_ADAPTER_SIOSL_ISSUED,
503339f4f4eSChristof Schmitt 				&adapter->status);
504339f4f4eSChristof Schmitt }
505