xref: /openbmc/linux/drivers/s390/scsi/zfcp_qdio.c (revision 1aae0560d160ee6ebef927a35e4f405306a079df)
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 
175d4e2262SChristof Schmitt #define QBUFF_PER_PAGE		(PAGE_SIZE / sizeof(struct qdio_buffer))
181da177e4SLinus Torvalds 
1986a9668aSSwen Schillig static bool enable_multibuffer;
2086a9668aSSwen Schillig module_param_named(datarouter, enable_multibuffer, bool, 0400);
2186a9668aSSwen Schillig MODULE_PARM_DESC(datarouter, "Enable hardware data router support");
2286a9668aSSwen Schillig 
2300bab910SSwen Schillig static int zfcp_qdio_buffers_enqueue(struct qdio_buffer **sbal)
24b4e44590SSwen Schillig {
25b4e44590SSwen Schillig 	int pos;
26b4e44590SSwen Schillig 
27b4e44590SSwen Schillig 	for (pos = 0; pos < QDIO_MAX_BUFFERS_PER_Q; pos += QBUFF_PER_PAGE) {
2800bab910SSwen Schillig 		sbal[pos] = (struct qdio_buffer *) get_zeroed_page(GFP_KERNEL);
2900bab910SSwen Schillig 		if (!sbal[pos])
30b4e44590SSwen Schillig 			return -ENOMEM;
31b4e44590SSwen Schillig 	}
32b4e44590SSwen Schillig 	for (pos = 0; pos < QDIO_MAX_BUFFERS_PER_Q; pos++)
33b4e44590SSwen Schillig 		if (pos % QBUFF_PER_PAGE)
3400bab910SSwen Schillig 			sbal[pos] = sbal[pos - 1] + 1;
35b4e44590SSwen Schillig 	return 0;
361da177e4SLinus Torvalds }
371da177e4SLinus Torvalds 
38339f4f4eSChristof Schmitt static void zfcp_qdio_handler_error(struct zfcp_qdio *qdio, char *id,
39339f4f4eSChristof Schmitt 				    unsigned int qdio_err)
4000bab910SSwen Schillig {
41564e1c86SSwen Schillig 	struct zfcp_adapter *adapter = qdio->adapter;
42564e1c86SSwen Schillig 
43ff3b24faSChristof Schmitt 	dev_warn(&adapter->ccw_device->dev, "A QDIO problem occurred\n");
4400bab910SSwen Schillig 
4586a9668aSSwen Schillig 	if (qdio_err & QDIO_ERROR_SLSB_STATE) {
46339f4f4eSChristof Schmitt 		zfcp_qdio_siosl(adapter);
4786a9668aSSwen Schillig 		zfcp_erp_adapter_shutdown(adapter, 0, id);
4886a9668aSSwen Schillig 		return;
4986a9668aSSwen Schillig 	}
5000bab910SSwen Schillig 	zfcp_erp_adapter_reopen(adapter,
5100bab910SSwen Schillig 				ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
52ea4a3a6aSSwen Schillig 				ZFCP_STATUS_COMMON_ERP_FAILED, id);
5300bab910SSwen Schillig }
5400bab910SSwen Schillig 
555d4e2262SChristof Schmitt static void zfcp_qdio_zero_sbals(struct qdio_buffer *sbal[], int first, int cnt)
565d4e2262SChristof Schmitt {
575d4e2262SChristof Schmitt 	int i, sbal_idx;
585d4e2262SChristof Schmitt 
595d4e2262SChristof Schmitt 	for (i = first; i < first + cnt; i++) {
605d4e2262SChristof Schmitt 		sbal_idx = i % QDIO_MAX_BUFFERS_PER_Q;
615d4e2262SChristof Schmitt 		memset(sbal[sbal_idx], 0, sizeof(struct qdio_buffer));
625d4e2262SChristof Schmitt 	}
635d4e2262SChristof Schmitt }
645d4e2262SChristof Schmitt 
6594506fd1SMartin Peschke /* this needs to be called prior to updating the queue fill level */
6641e05a12SHeiko Carstens static inline void zfcp_qdio_account(struct zfcp_qdio *qdio)
6794506fd1SMartin Peschke {
6841e05a12SHeiko Carstens 	unsigned long long now, span;
69706eca49SSwen Schillig 	int used;
7094506fd1SMartin Peschke 
71*1aae0560SHeiko Carstens 	now = get_tod_clock_monotonic();
7241e05a12SHeiko Carstens 	span = (now - qdio->req_q_time) >> 12;
73706eca49SSwen Schillig 	used = QDIO_MAX_BUFFERS_PER_Q - atomic_read(&qdio->req_q_free);
74564e1c86SSwen Schillig 	qdio->req_q_util += used * span;
75564e1c86SSwen Schillig 	qdio->req_q_time = now;
7694506fd1SMartin Peschke }
7794506fd1SMartin Peschke 
78779e6e1cSJan Glauber static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err,
79706eca49SSwen Schillig 			      int queue_no, int idx, int count,
8000bab910SSwen Schillig 			      unsigned long parm)
8100bab910SSwen Schillig {
82564e1c86SSwen Schillig 	struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm;
8300bab910SSwen Schillig 
84779e6e1cSJan Glauber 	if (unlikely(qdio_err)) {
85339f4f4eSChristof Schmitt 		zfcp_qdio_handler_error(qdio, "qdireq1", qdio_err);
8600bab910SSwen Schillig 		return;
8700bab910SSwen Schillig 	}
8800bab910SSwen Schillig 
8900bab910SSwen Schillig 	/* cleanup all SBALs being program-owned now */
90706eca49SSwen Schillig 	zfcp_qdio_zero_sbals(qdio->req_q, idx, count);
9100bab910SSwen Schillig 
9244a24cb3SChristof Schmitt 	spin_lock_irq(&qdio->stat_lock);
93564e1c86SSwen Schillig 	zfcp_qdio_account(qdio);
9444a24cb3SChristof Schmitt 	spin_unlock_irq(&qdio->stat_lock);
95706eca49SSwen Schillig 	atomic_add(count, &qdio->req_q_free);
96564e1c86SSwen Schillig 	wake_up(&qdio->req_q_wq);
9700bab910SSwen Schillig }
9800bab910SSwen Schillig 
99779e6e1cSJan Glauber static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err,
100706eca49SSwen Schillig 			       int queue_no, int idx, int count,
10100bab910SSwen Schillig 			       unsigned long parm)
10200bab910SSwen Schillig {
103564e1c86SSwen Schillig 	struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm;
10486a9668aSSwen Schillig 	struct zfcp_adapter *adapter = qdio->adapter;
10586a9668aSSwen Schillig 	int sbal_no, sbal_idx;
10601e60527SSteffen Maier 
10701e60527SSteffen Maier 	if (unlikely(qdio_err)) {
10801e60527SSteffen Maier 		if (zfcp_adapter_multi_buffer_active(adapter)) {
10986a9668aSSwen Schillig 			void *pl[ZFCP_QDIO_MAX_SBALS_PER_REQ + 1];
11001e60527SSteffen Maier 			struct qdio_buffer_element *sbale;
11186a9668aSSwen Schillig 			u64 req_id;
11286a9668aSSwen Schillig 			u8 scount;
11300bab910SSwen Schillig 
11401e60527SSteffen Maier 			memset(pl, 0,
11501e60527SSteffen Maier 			       ZFCP_QDIO_MAX_SBALS_PER_REQ * sizeof(void *));
11686a9668aSSwen Schillig 			sbale = qdio->res_q[idx]->element;
11786a9668aSSwen Schillig 			req_id = (u64) sbale->addr;
11801e60527SSteffen Maier 			scount = min(sbale->scount + 1,
11901e60527SSteffen Maier 				     ZFCP_QDIO_MAX_SBALS_PER_REQ + 1);
12001e60527SSteffen Maier 				     /* incl. signaling SBAL */
12186a9668aSSwen Schillig 
12286a9668aSSwen Schillig 			for (sbal_no = 0; sbal_no < scount; sbal_no++) {
12386a9668aSSwen Schillig 				sbal_idx = (idx + sbal_no) %
12486a9668aSSwen Schillig 					QDIO_MAX_BUFFERS_PER_Q;
12586a9668aSSwen Schillig 				pl[sbal_no] = qdio->res_q[sbal_idx];
12686a9668aSSwen Schillig 			}
12786a9668aSSwen Schillig 			zfcp_dbf_hba_def_err(adapter, req_id, scount, pl);
12886a9668aSSwen Schillig 		}
129339f4f4eSChristof Schmitt 		zfcp_qdio_handler_error(qdio, "qdires1", qdio_err);
13000bab910SSwen Schillig 		return;
13100bab910SSwen Schillig 	}
13200bab910SSwen Schillig 
1331da177e4SLinus Torvalds 	/*
1341da177e4SLinus Torvalds 	 * go through all SBALs from input queue currently
1351da177e4SLinus Torvalds 	 * returned by QDIO layer
1361da177e4SLinus Torvalds 	 */
13700bab910SSwen Schillig 	for (sbal_no = 0; sbal_no < count; sbal_no++) {
138706eca49SSwen Schillig 		sbal_idx = (idx + sbal_no) % QDIO_MAX_BUFFERS_PER_Q;
1391da177e4SLinus Torvalds 		/* go through all SBALEs of SBAL */
140564e1c86SSwen Schillig 		zfcp_fsf_reqid_check(qdio, sbal_idx);
1411da177e4SLinus Torvalds 	}
1421da177e4SLinus Torvalds 
1431da177e4SLinus Torvalds 	/*
144706eca49SSwen Schillig 	 * put SBALs back to response queue
1451da177e4SLinus Torvalds 	 */
146706eca49SSwen Schillig 	if (do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT, 0, idx, count))
147ea4a3a6aSSwen Schillig 		zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdires2");
1481da177e4SLinus Torvalds }
1491da177e4SLinus Torvalds 
15044cc76f2SSwen Schillig static struct qdio_buffer_element *
1511674b405SChristof Schmitt zfcp_qdio_sbal_chain(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
1521da177e4SLinus Torvalds {
15344cc76f2SSwen Schillig 	struct qdio_buffer_element *sbale;
1541da177e4SLinus Torvalds 
1551da177e4SLinus Torvalds 	/* set last entry flag in current SBALE of current SBAL */
156564e1c86SSwen Schillig 	sbale = zfcp_qdio_sbale_curr(qdio, q_req);
1573ec90878SJan Glauber 	sbale->eflags |= SBAL_EFLAGS_LAST_ENTRY;
1581da177e4SLinus Torvalds 
1591da177e4SLinus Torvalds 	/* don't exceed last allowed SBAL */
16042428f74SSwen Schillig 	if (q_req->sbal_last == q_req->sbal_limit)
1611da177e4SLinus Torvalds 		return NULL;
1621da177e4SLinus Torvalds 
1631da177e4SLinus Torvalds 	/* set chaining flag in first SBALE of current SBAL */
164564e1c86SSwen Schillig 	sbale = zfcp_qdio_sbale_req(qdio, q_req);
1653ec90878SJan Glauber 	sbale->sflags |= SBAL_SFLAGS0_MORE_SBALS;
1661da177e4SLinus Torvalds 
1671da177e4SLinus Torvalds 	/* calculate index of next SBAL */
16842428f74SSwen Schillig 	q_req->sbal_last++;
16942428f74SSwen Schillig 	q_req->sbal_last %= QDIO_MAX_BUFFERS_PER_Q;
1701da177e4SLinus Torvalds 
1711da177e4SLinus Torvalds 	/* keep this requests number of SBALs up-to-date */
17242428f74SSwen Schillig 	q_req->sbal_number++;
17301b04759SSwen Schillig 	BUG_ON(q_req->sbal_number > ZFCP_QDIO_MAX_SBALS_PER_REQ);
1741da177e4SLinus Torvalds 
1751da177e4SLinus Torvalds 	/* start at first SBALE of new SBAL */
17642428f74SSwen Schillig 	q_req->sbale_curr = 0;
1771da177e4SLinus Torvalds 
1781da177e4SLinus Torvalds 	/* set storage-block type for new SBAL */
179564e1c86SSwen Schillig 	sbale = zfcp_qdio_sbale_curr(qdio, q_req);
1803ec90878SJan Glauber 	sbale->sflags |= q_req->sbtype;
1811da177e4SLinus Torvalds 
1821da177e4SLinus Torvalds 	return sbale;
1831da177e4SLinus Torvalds }
1841da177e4SLinus Torvalds 
18544cc76f2SSwen Schillig static struct qdio_buffer_element *
1861674b405SChristof Schmitt zfcp_qdio_sbale_next(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
1871da177e4SLinus Torvalds {
18886a9668aSSwen Schillig 	if (q_req->sbale_curr == qdio->max_sbale_per_sbal - 1)
1891674b405SChristof Schmitt 		return zfcp_qdio_sbal_chain(qdio, q_req);
19042428f74SSwen Schillig 	q_req->sbale_curr++;
191564e1c86SSwen Schillig 	return zfcp_qdio_sbale_curr(qdio, q_req);
1921da177e4SLinus Torvalds }
1931da177e4SLinus Torvalds 
1941da177e4SLinus Torvalds /**
1951da177e4SLinus Torvalds  * zfcp_qdio_sbals_from_sg - fill SBALs from scatter-gather list
1961674b405SChristof Schmitt  * @qdio: pointer to struct zfcp_qdio
1971674b405SChristof Schmitt  * @q_req: pointer to struct zfcp_qdio_req
1981da177e4SLinus Torvalds  * @sg: scatter-gather list
1991da177e4SLinus Torvalds  * @max_sbals: upper bound for number of SBALs to be used
20086a9668aSSwen Schillig  * Returns: zero or -EINVAL on error
2011da177e4SLinus Torvalds  */
20234c2b712SChristof Schmitt int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
20301b04759SSwen Schillig 			    struct scatterlist *sg)
2041da177e4SLinus Torvalds {
20544cc76f2SSwen Schillig 	struct qdio_buffer_element *sbale;
2061da177e4SLinus Torvalds 
20700bab910SSwen Schillig 	/* set storage-block type for this request */
208564e1c86SSwen Schillig 	sbale = zfcp_qdio_sbale_req(qdio, q_req);
2093ec90878SJan Glauber 	sbale->sflags |= q_req->sbtype;
2101da177e4SLinus Torvalds 
21100bab910SSwen Schillig 	for (; sg; sg = sg_next(sg)) {
2121674b405SChristof Schmitt 		sbale = zfcp_qdio_sbale_next(qdio, q_req);
21368322984SChristof Schmitt 		if (!sbale) {
21468322984SChristof Schmitt 			atomic_inc(&qdio->req_q_full);
215706eca49SSwen Schillig 			zfcp_qdio_zero_sbals(qdio->req_q, q_req->sbal_first,
216706eca49SSwen Schillig 					     q_req->sbal_number);
21768322984SChristof Schmitt 			return -EINVAL;
21868322984SChristof Schmitt 		}
21968322984SChristof Schmitt 		sbale->addr = sg_virt(sg);
22068322984SChristof Schmitt 		sbale->length = sg->length;
2211da177e4SLinus Torvalds 	}
22286a9668aSSwen Schillig 	return 0;
2231da177e4SLinus Torvalds }
2241da177e4SLinus Torvalds 
2256b9e1520SChristof Schmitt static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio)
2266b9e1520SChristof Schmitt {
22744a24cb3SChristof Schmitt 	spin_lock_irq(&qdio->req_q_lock);
228706eca49SSwen Schillig 	if (atomic_read(&qdio->req_q_free) ||
229c2af7545SChristof Schmitt 	    !(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
2306b9e1520SChristof Schmitt 		return 1;
23144a24cb3SChristof Schmitt 	spin_unlock_irq(&qdio->req_q_lock);
2326b9e1520SChristof Schmitt 	return 0;
2336b9e1520SChristof Schmitt }
2346b9e1520SChristof Schmitt 
2356b9e1520SChristof Schmitt /**
2366b9e1520SChristof Schmitt  * zfcp_qdio_sbal_get - get free sbal in request queue, wait if necessary
2376b9e1520SChristof Schmitt  * @qdio: pointer to struct zfcp_qdio
2386b9e1520SChristof Schmitt  *
2396b9e1520SChristof Schmitt  * The req_q_lock must be held by the caller of this function, and
2406b9e1520SChristof Schmitt  * this function may only be called from process context; it will
2416b9e1520SChristof Schmitt  * sleep when waiting for a free sbal.
2426b9e1520SChristof Schmitt  *
2436b9e1520SChristof Schmitt  * Returns: 0 on success, -EIO if there is no free sbal after waiting.
2446b9e1520SChristof Schmitt  */
2456b9e1520SChristof Schmitt int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio)
2466b9e1520SChristof Schmitt {
2476b9e1520SChristof Schmitt 	long ret;
2486b9e1520SChristof Schmitt 
24944a24cb3SChristof Schmitt 	spin_unlock_irq(&qdio->req_q_lock);
2506b9e1520SChristof Schmitt 	ret = wait_event_interruptible_timeout(qdio->req_q_wq,
2516b9e1520SChristof Schmitt 			       zfcp_qdio_sbal_check(qdio), 5 * HZ);
252c2af7545SChristof Schmitt 
253c2af7545SChristof Schmitt 	if (!(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
254c2af7545SChristof Schmitt 		return -EIO;
255c2af7545SChristof Schmitt 
2566b9e1520SChristof Schmitt 	if (ret > 0)
2576b9e1520SChristof Schmitt 		return 0;
258c2af7545SChristof Schmitt 
2596b9e1520SChristof Schmitt 	if (!ret) {
2606b9e1520SChristof Schmitt 		atomic_inc(&qdio->req_q_full);
2616b9e1520SChristof Schmitt 		/* assume hanging outbound queue, try queue recovery */
262ea4a3a6aSSwen Schillig 		zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdsbg_1");
2636b9e1520SChristof Schmitt 	}
2646b9e1520SChristof Schmitt 
26544a24cb3SChristof Schmitt 	spin_lock_irq(&qdio->req_q_lock);
2666b9e1520SChristof Schmitt 	return -EIO;
2676b9e1520SChristof Schmitt }
2686b9e1520SChristof Schmitt 
2691da177e4SLinus Torvalds /**
27000bab910SSwen Schillig  * zfcp_qdio_send - set PCI flag in first SBALE and send req to QDIO
271564e1c86SSwen Schillig  * @qdio: pointer to struct zfcp_qdio
27234c2b712SChristof Schmitt  * @q_req: pointer to struct zfcp_qdio_req
27300bab910SSwen Schillig  * Returns: 0 on success, error otherwise
2741da177e4SLinus Torvalds  */
27534c2b712SChristof Schmitt int zfcp_qdio_send(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
2761da177e4SLinus Torvalds {
27721ddaa53SChristof Schmitt 	int retval;
278706eca49SSwen Schillig 	u8 sbal_number = q_req->sbal_number;
27900bab910SSwen Schillig 
28044a24cb3SChristof Schmitt 	spin_lock(&qdio->stat_lock);
281564e1c86SSwen Schillig 	zfcp_qdio_account(qdio);
28244a24cb3SChristof Schmitt 	spin_unlock(&qdio->stat_lock);
28394506fd1SMartin Peschke 
284706eca49SSwen Schillig 	retval = do_QDIO(qdio->adapter->ccw_device, QDIO_FLAG_SYNC_OUTPUT, 0,
285706eca49SSwen Schillig 			 q_req->sbal_first, sbal_number);
286706eca49SSwen Schillig 
28700bab910SSwen Schillig 	if (unlikely(retval)) {
288706eca49SSwen Schillig 		zfcp_qdio_zero_sbals(qdio->req_q, q_req->sbal_first,
289706eca49SSwen Schillig 				     sbal_number);
29000bab910SSwen Schillig 		return retval;
2911da177e4SLinus Torvalds 	}
2921da177e4SLinus Torvalds 
29300bab910SSwen Schillig 	/* account for transferred buffers */
294706eca49SSwen Schillig 	atomic_sub(sbal_number, &qdio->req_q_free);
295706eca49SSwen Schillig 	qdio->req_q_idx += sbal_number;
296706eca49SSwen Schillig 	qdio->req_q_idx %= QDIO_MAX_BUFFERS_PER_Q;
297706eca49SSwen Schillig 
29800bab910SSwen Schillig 	return 0;
29900bab910SSwen Schillig }
30000bab910SSwen Schillig 
301564e1c86SSwen Schillig 
302564e1c86SSwen Schillig static void zfcp_qdio_setup_init_data(struct qdio_initialize *id,
303564e1c86SSwen Schillig 				      struct zfcp_qdio *qdio)
304564e1c86SSwen Schillig {
305d36deae7SJan Glauber 	memset(id, 0, sizeof(*id));
306564e1c86SSwen Schillig 	id->cdev = qdio->adapter->ccw_device;
307564e1c86SSwen Schillig 	id->q_format = QDIO_ZFCP_QFMT;
308564e1c86SSwen Schillig 	memcpy(id->adapter_name, dev_name(&id->cdev->dev), 8);
309564e1c86SSwen Schillig 	ASCEBC(id->adapter_name, 8);
310dcc18f48SChristof Schmitt 	id->qib_rflags = QIB_RFLAGS_ENABLE_DATA_DIV;
31186a9668aSSwen Schillig 	if (enable_multibuffer)
31286a9668aSSwen Schillig 		id->qdr_ac |= QDR_AC_MULTI_BUFFER_ENABLE;
313564e1c86SSwen Schillig 	id->no_input_qs = 1;
314564e1c86SSwen Schillig 	id->no_output_qs = 1;
315564e1c86SSwen Schillig 	id->input_handler = zfcp_qdio_int_resp;
316564e1c86SSwen Schillig 	id->output_handler = zfcp_qdio_int_req;
317564e1c86SSwen Schillig 	id->int_parm = (unsigned long) qdio;
318706eca49SSwen Schillig 	id->input_sbal_addr_array = (void **) (qdio->res_q);
319706eca49SSwen Schillig 	id->output_sbal_addr_array = (void **) (qdio->req_q);
3203d6c76ffSJan Glauber 	id->scan_threshold =
3213d6c76ffSJan Glauber 		QDIO_MAX_BUFFERS_PER_Q - ZFCP_QDIO_MAX_SBALS_PER_REQ * 2;
322564e1c86SSwen Schillig }
323dcc18f48SChristof Schmitt 
32400bab910SSwen Schillig /**
32500bab910SSwen Schillig  * zfcp_qdio_allocate - allocate queue memory and initialize QDIO data
32600bab910SSwen Schillig  * @adapter: pointer to struct zfcp_adapter
32700bab910SSwen Schillig  * Returns: -ENOMEM on memory allocation error or return value from
32800bab910SSwen Schillig  *          qdio_allocate
32900bab910SSwen Schillig  */
330d5a282a1SSwen Schillig static int zfcp_qdio_allocate(struct zfcp_qdio *qdio)
33100bab910SSwen Schillig {
332564e1c86SSwen Schillig 	struct qdio_initialize init_data;
33300bab910SSwen Schillig 
334706eca49SSwen Schillig 	if (zfcp_qdio_buffers_enqueue(qdio->req_q) ||
335706eca49SSwen Schillig 	    zfcp_qdio_buffers_enqueue(qdio->res_q))
33600bab910SSwen Schillig 		return -ENOMEM;
33700bab910SSwen Schillig 
338564e1c86SSwen Schillig 	zfcp_qdio_setup_init_data(&init_data, qdio);
3393d63d3b4SChristof Schmitt 	init_waitqueue_head(&qdio->req_q_wq);
34000bab910SSwen Schillig 
341564e1c86SSwen Schillig 	return qdio_allocate(&init_data);
34200bab910SSwen Schillig }
34300bab910SSwen Schillig 
34400bab910SSwen Schillig /**
34500bab910SSwen Schillig  * zfcp_close_qdio - close qdio queues for an adapter
346564e1c86SSwen Schillig  * @qdio: pointer to structure zfcp_qdio
34700bab910SSwen Schillig  */
348564e1c86SSwen Schillig void zfcp_qdio_close(struct zfcp_qdio *qdio)
34900bab910SSwen Schillig {
350706eca49SSwen Schillig 	struct zfcp_adapter *adapter = qdio->adapter;
351706eca49SSwen Schillig 	int idx, count;
35200bab910SSwen Schillig 
353706eca49SSwen Schillig 	if (!(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
35400bab910SSwen Schillig 		return;
35500bab910SSwen Schillig 
35600bab910SSwen Schillig 	/* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */
35744a24cb3SChristof Schmitt 	spin_lock_irq(&qdio->req_q_lock);
358706eca49SSwen Schillig 	atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
35944a24cb3SChristof Schmitt 	spin_unlock_irq(&qdio->req_q_lock);
36000bab910SSwen Schillig 
361c2af7545SChristof Schmitt 	wake_up(&qdio->req_q_wq);
362c2af7545SChristof Schmitt 
363706eca49SSwen Schillig 	qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR);
36400bab910SSwen Schillig 
36500bab910SSwen Schillig 	/* cleanup used outbound sbals */
366706eca49SSwen Schillig 	count = atomic_read(&qdio->req_q_free);
36700bab910SSwen Schillig 	if (count < QDIO_MAX_BUFFERS_PER_Q) {
368706eca49SSwen Schillig 		idx = (qdio->req_q_idx + count) % QDIO_MAX_BUFFERS_PER_Q;
36900bab910SSwen Schillig 		count = QDIO_MAX_BUFFERS_PER_Q - count;
370706eca49SSwen Schillig 		zfcp_qdio_zero_sbals(qdio->req_q, idx, count);
37100bab910SSwen Schillig 	}
372706eca49SSwen Schillig 	qdio->req_q_idx = 0;
373706eca49SSwen Schillig 	atomic_set(&qdio->req_q_free, 0);
37400bab910SSwen Schillig }
37500bab910SSwen Schillig 
37600bab910SSwen Schillig /**
37700bab910SSwen Schillig  * zfcp_qdio_open - prepare and initialize response queue
378564e1c86SSwen Schillig  * @qdio: pointer to struct zfcp_qdio
37900bab910SSwen Schillig  * Returns: 0 on success, otherwise -EIO
38000bab910SSwen Schillig  */
381564e1c86SSwen Schillig int zfcp_qdio_open(struct zfcp_qdio *qdio)
38200bab910SSwen Schillig {
38344cc76f2SSwen Schillig 	struct qdio_buffer_element *sbale;
384564e1c86SSwen Schillig 	struct qdio_initialize init_data;
385706eca49SSwen Schillig 	struct zfcp_adapter *adapter = qdio->adapter;
386706eca49SSwen Schillig 	struct ccw_device *cdev = adapter->ccw_device;
387dcc18f48SChristof Schmitt 	struct qdio_ssqd_desc ssqd;
38800bab910SSwen Schillig 	int cc;
38900bab910SSwen Schillig 
390706eca49SSwen Schillig 	if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)
39100bab910SSwen Schillig 		return -EIO;
39200bab910SSwen Schillig 
393339f4f4eSChristof Schmitt 	atomic_clear_mask(ZFCP_STATUS_ADAPTER_SIOSL_ISSUED,
394339f4f4eSChristof Schmitt 			  &qdio->adapter->status);
395339f4f4eSChristof Schmitt 
396564e1c86SSwen Schillig 	zfcp_qdio_setup_init_data(&init_data, qdio);
397564e1c86SSwen Schillig 
398564e1c86SSwen Schillig 	if (qdio_establish(&init_data))
399ff3b24faSChristof Schmitt 		goto failed_establish;
40000bab910SSwen Schillig 
401dcc18f48SChristof Schmitt 	if (qdio_get_ssqd_desc(init_data.cdev, &ssqd))
402dcc18f48SChristof Schmitt 		goto failed_qdio;
403dcc18f48SChristof Schmitt 
404dcc18f48SChristof Schmitt 	if (ssqd.qdioac2 & CHSC_AC2_DATA_DIV_ENABLED)
405dcc18f48SChristof Schmitt 		atomic_set_mask(ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED,
406dcc18f48SChristof Schmitt 				&qdio->adapter->status);
407dcc18f48SChristof Schmitt 
40886a9668aSSwen Schillig 	if (ssqd.qdioac2 & CHSC_AC2_MULTI_BUFFER_ENABLED) {
40986a9668aSSwen Schillig 		atomic_set_mask(ZFCP_STATUS_ADAPTER_MB_ACT, &adapter->status);
41086a9668aSSwen Schillig 		qdio->max_sbale_per_sbal = QDIO_MAX_ELEMENTS_PER_BUFFER;
41186a9668aSSwen Schillig 	} else {
41286a9668aSSwen Schillig 		atomic_clear_mask(ZFCP_STATUS_ADAPTER_MB_ACT, &adapter->status);
41386a9668aSSwen Schillig 		qdio->max_sbale_per_sbal = QDIO_MAX_ELEMENTS_PER_BUFFER - 1;
41486a9668aSSwen Schillig 	}
41586a9668aSSwen Schillig 
41686a9668aSSwen Schillig 	qdio->max_sbale_per_req =
41786a9668aSSwen Schillig 		ZFCP_QDIO_MAX_SBALS_PER_REQ * qdio->max_sbale_per_sbal
41886a9668aSSwen Schillig 		- 2;
419564e1c86SSwen Schillig 	if (qdio_activate(cdev))
42000bab910SSwen Schillig 		goto failed_qdio;
42100bab910SSwen Schillig 
42200bab910SSwen Schillig 	for (cc = 0; cc < QDIO_MAX_BUFFERS_PER_Q; cc++) {
423706eca49SSwen Schillig 		sbale = &(qdio->res_q[cc]->element[0]);
42400bab910SSwen Schillig 		sbale->length = 0;
4253ec90878SJan Glauber 		sbale->eflags = SBAL_EFLAGS_LAST_ENTRY;
4263ec90878SJan Glauber 		sbale->sflags = 0;
42700bab910SSwen Schillig 		sbale->addr = NULL;
42800bab910SSwen Schillig 	}
42900bab910SSwen Schillig 
430706eca49SSwen Schillig 	if (do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT, 0, 0, QDIO_MAX_BUFFERS_PER_Q))
43100bab910SSwen Schillig 		goto failed_qdio;
43200bab910SSwen Schillig 
43325985edcSLucas De Marchi 	/* set index of first available SBALS / number of available SBALS */
434706eca49SSwen Schillig 	qdio->req_q_idx = 0;
435706eca49SSwen Schillig 	atomic_set(&qdio->req_q_free, QDIO_MAX_BUFFERS_PER_Q);
4363d63d3b4SChristof Schmitt 	atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &qdio->adapter->status);
43700bab910SSwen Schillig 
43886a9668aSSwen Schillig 	if (adapter->scsi_host) {
43986a9668aSSwen Schillig 		adapter->scsi_host->sg_tablesize = qdio->max_sbale_per_req;
44086a9668aSSwen Schillig 		adapter->scsi_host->max_sectors = qdio->max_sbale_per_req * 8;
44186a9668aSSwen Schillig 	}
44286a9668aSSwen Schillig 
44300bab910SSwen Schillig 	return 0;
44400bab910SSwen Schillig 
44500bab910SSwen Schillig failed_qdio:
446564e1c86SSwen Schillig 	qdio_shutdown(cdev, QDIO_FLAG_CLEANUP_USING_CLEAR);
447ff3b24faSChristof Schmitt failed_establish:
448564e1c86SSwen Schillig 	dev_err(&cdev->dev,
449ff3b24faSChristof Schmitt 		"Setting up the QDIO connection to the FCP adapter failed\n");
45000bab910SSwen Schillig 	return -EIO;
45100bab910SSwen Schillig }
452d5a282a1SSwen Schillig 
453d5a282a1SSwen Schillig void zfcp_qdio_destroy(struct zfcp_qdio *qdio)
454d5a282a1SSwen Schillig {
455d5a282a1SSwen Schillig 	int p;
456d5a282a1SSwen Schillig 
457d5a282a1SSwen Schillig 	if (!qdio)
458d5a282a1SSwen Schillig 		return;
459d5a282a1SSwen Schillig 
460d5a282a1SSwen Schillig 	if (qdio->adapter->ccw_device)
461d5a282a1SSwen Schillig 		qdio_free(qdio->adapter->ccw_device);
462d5a282a1SSwen Schillig 
463d5a282a1SSwen Schillig 	for (p = 0; p < QDIO_MAX_BUFFERS_PER_Q; p += QBUFF_PER_PAGE) {
464706eca49SSwen Schillig 		free_page((unsigned long) qdio->req_q[p]);
465706eca49SSwen Schillig 		free_page((unsigned long) qdio->res_q[p]);
466d5a282a1SSwen Schillig 	}
467d5a282a1SSwen Schillig 
468d5a282a1SSwen Schillig 	kfree(qdio);
469d5a282a1SSwen Schillig }
470d5a282a1SSwen Schillig 
471d5a282a1SSwen Schillig int zfcp_qdio_setup(struct zfcp_adapter *adapter)
472d5a282a1SSwen Schillig {
473d5a282a1SSwen Schillig 	struct zfcp_qdio *qdio;
474d5a282a1SSwen Schillig 
475d5a282a1SSwen Schillig 	qdio = kzalloc(sizeof(struct zfcp_qdio), GFP_KERNEL);
476d5a282a1SSwen Schillig 	if (!qdio)
477d5a282a1SSwen Schillig 		return -ENOMEM;
478d5a282a1SSwen Schillig 
479d5a282a1SSwen Schillig 	qdio->adapter = adapter;
480d5a282a1SSwen Schillig 
481d5a282a1SSwen Schillig 	if (zfcp_qdio_allocate(qdio)) {
482d5a282a1SSwen Schillig 		zfcp_qdio_destroy(qdio);
483d5a282a1SSwen Schillig 		return -ENOMEM;
484d5a282a1SSwen Schillig 	}
485d5a282a1SSwen Schillig 
486d5a282a1SSwen Schillig 	spin_lock_init(&qdio->req_q_lock);
487d5a282a1SSwen Schillig 	spin_lock_init(&qdio->stat_lock);
488d5a282a1SSwen Schillig 
489d5a282a1SSwen Schillig 	adapter->qdio = qdio;
490d5a282a1SSwen Schillig 	return 0;
491d5a282a1SSwen Schillig }
492d5a282a1SSwen Schillig 
493339f4f4eSChristof Schmitt /**
494339f4f4eSChristof Schmitt  * zfcp_qdio_siosl - Trigger logging in FCP channel
495339f4f4eSChristof Schmitt  * @adapter: The zfcp_adapter where to trigger logging
496339f4f4eSChristof Schmitt  *
497339f4f4eSChristof Schmitt  * Call the cio siosl function to trigger hardware logging.  This
498339f4f4eSChristof Schmitt  * wrapper function sets a flag to ensure hardware logging is only
499339f4f4eSChristof Schmitt  * triggered once before going through qdio shutdown.
500339f4f4eSChristof Schmitt  *
501339f4f4eSChristof Schmitt  * The triggers are always run from qdio tasklet context, so no
502339f4f4eSChristof Schmitt  * additional synchronization is necessary.
503339f4f4eSChristof Schmitt  */
504339f4f4eSChristof Schmitt void zfcp_qdio_siosl(struct zfcp_adapter *adapter)
505339f4f4eSChristof Schmitt {
506339f4f4eSChristof Schmitt 	int rc;
507339f4f4eSChristof Schmitt 
508339f4f4eSChristof Schmitt 	if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_SIOSL_ISSUED)
509339f4f4eSChristof Schmitt 		return;
510339f4f4eSChristof Schmitt 
511339f4f4eSChristof Schmitt 	rc = ccw_device_siosl(adapter->ccw_device);
512339f4f4eSChristof Schmitt 	if (!rc)
513339f4f4eSChristof Schmitt 		atomic_set_mask(ZFCP_STATUS_ADAPTER_SIOSL_ISSUED,
514339f4f4eSChristof Schmitt 				&adapter->status);
515339f4f4eSChristof Schmitt }
516