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