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