aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/scsi/zfcp_qdio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/scsi/zfcp_qdio.c')
-rw-r--r--drivers/s390/scsi/zfcp_qdio.c113
1 files changed, 32 insertions, 81 deletions
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index bdf5782b8a7a..c408badd2ae9 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -47,103 +47,56 @@ static int zfcp_qdio_handler_error_check(struct zfcp_adapter *,
47#define ZFCP_LOG_AREA ZFCP_LOG_AREA_QDIO 47#define ZFCP_LOG_AREA ZFCP_LOG_AREA_QDIO
48 48
49/* 49/*
50 * Allocates BUFFER memory to each of the pointers of the qdio_buffer_t 50 * Frees BUFFER memory for each of the pointers of the struct qdio_buffer array
51 * array in the adapter struct. 51 * in the adapter struct sbuf is the pointer array.
52 * Cur_buf is the pointer array and count can be any number of required
53 * buffers, the page-fitting arithmetic is done entirely within this funciton.
54 * 52 *
55 * returns: number of buffers allocated
56 * locks: must only be called with zfcp_data.config_sema taken 53 * locks: must only be called with zfcp_data.config_sema taken
57 */ 54 */
58static int 55static void
59zfcp_qdio_buffers_enqueue(struct qdio_buffer **cur_buf, int count) 56zfcp_qdio_buffers_dequeue(struct qdio_buffer **sbuf)
60{ 57{
61 int buf_pos; 58 int pos;
62 int qdio_buffers_per_page;
63 int page_pos = 0;
64 struct qdio_buffer *first_in_page = NULL;
65
66 qdio_buffers_per_page = PAGE_SIZE / sizeof (struct qdio_buffer);
67 ZFCP_LOG_TRACE("buffers_per_page=%d\n", qdio_buffers_per_page);
68
69 for (buf_pos = 0; buf_pos < count; buf_pos++) {
70 if (page_pos == 0) {
71 cur_buf[buf_pos] = (struct qdio_buffer *)
72 get_zeroed_page(GFP_KERNEL);
73 if (cur_buf[buf_pos] == NULL) {
74 ZFCP_LOG_INFO("error: allocation of "
75 "QDIO buffer failed \n");
76 goto out;
77 }
78 first_in_page = cur_buf[buf_pos];
79 } else {
80 cur_buf[buf_pos] = first_in_page + page_pos;
81 59
82 } 60 for (pos = 0; pos < QDIO_MAX_BUFFERS_PER_Q; pos += QBUFF_PER_PAGE)
83 /* was initialised to zero */ 61 free_page((unsigned long) sbuf[pos]);
84 page_pos++;
85 page_pos %= qdio_buffers_per_page;
86 }
87 out:
88 return buf_pos;
89} 62}
90 63
91/* 64/*
92 * Frees BUFFER memory for each of the pointers of the struct qdio_buffer array 65 * Allocates BUFFER memory to each of the pointers of the qdio_buffer_t
93 * in the adapter struct cur_buf is the pointer array and count can be any 66 * array in the adapter struct.
94 * number of buffers in the array that should be freed starting from buffer 0 67 * Cur_buf is the pointer array
95 * 68 *
69 * returns: zero on success else -ENOMEM
96 * locks: must only be called with zfcp_data.config_sema taken 70 * locks: must only be called with zfcp_data.config_sema taken
97 */ 71 */
98static void 72static int
99zfcp_qdio_buffers_dequeue(struct qdio_buffer **cur_buf, int count) 73zfcp_qdio_buffers_enqueue(struct qdio_buffer **sbuf)
100{ 74{
101 int buf_pos; 75 int pos;
102 int qdio_buffers_per_page;
103
104 qdio_buffers_per_page = PAGE_SIZE / sizeof (struct qdio_buffer);
105 ZFCP_LOG_TRACE("buffers_per_page=%d\n", qdio_buffers_per_page);
106 76
107 for (buf_pos = 0; buf_pos < count; buf_pos += qdio_buffers_per_page) 77 for (pos = 0; pos < QDIO_MAX_BUFFERS_PER_Q; pos += QBUFF_PER_PAGE) {
108 free_page((unsigned long) cur_buf[buf_pos]); 78 sbuf[pos] = (struct qdio_buffer *) get_zeroed_page(GFP_KERNEL);
109 return; 79 if (!sbuf[pos]) {
80 zfcp_qdio_buffers_dequeue(sbuf);
81 return -ENOMEM;
82 }
83 }
84 for (pos = 0; pos < QDIO_MAX_BUFFERS_PER_Q; pos++)
85 if (pos % QBUFF_PER_PAGE)
86 sbuf[pos] = sbuf[pos - 1] + 1;
87 return 0;
110} 88}
111 89
112/* locks: must only be called with zfcp_data.config_sema taken */ 90/* locks: must only be called with zfcp_data.config_sema taken */
113int 91int
114zfcp_qdio_allocate_queues(struct zfcp_adapter *adapter) 92zfcp_qdio_allocate_queues(struct zfcp_adapter *adapter)
115{ 93{
116 int buffer_count; 94 int ret;
117 int retval = 0;
118 95
119 buffer_count = 96 ret = zfcp_qdio_buffers_enqueue(adapter->request_queue.buffer);
120 zfcp_qdio_buffers_enqueue(&(adapter->request_queue.buffer[0]), 97 if (ret)
121 QDIO_MAX_BUFFERS_PER_Q); 98 return ret;
122 if (buffer_count < QDIO_MAX_BUFFERS_PER_Q) { 99 return zfcp_qdio_buffers_enqueue(adapter->response_queue.buffer);
123 ZFCP_LOG_DEBUG("only %d QDIO buffers allocated for request "
124 "queue\n", buffer_count);
125 zfcp_qdio_buffers_dequeue(&(adapter->request_queue.buffer[0]),
126 buffer_count);
127 retval = -ENOMEM;
128 goto out;
129 }
130
131 buffer_count =
132 zfcp_qdio_buffers_enqueue(&(adapter->response_queue.buffer[0]),
133 QDIO_MAX_BUFFERS_PER_Q);
134 if (buffer_count < QDIO_MAX_BUFFERS_PER_Q) {
135 ZFCP_LOG_DEBUG("only %d QDIO buffers allocated for response "
136 "queue", buffer_count);
137 zfcp_qdio_buffers_dequeue(&(adapter->response_queue.buffer[0]),
138 buffer_count);
139 ZFCP_LOG_TRACE("freeing request_queue buffers\n");
140 zfcp_qdio_buffers_dequeue(&(adapter->request_queue.buffer[0]),
141 QDIO_MAX_BUFFERS_PER_Q);
142 retval = -ENOMEM;
143 goto out;
144 }
145 out:
146 return retval;
147} 100}
148 101
149/* locks: must only be called with zfcp_data.config_sema taken */ 102/* locks: must only be called with zfcp_data.config_sema taken */
@@ -151,12 +104,10 @@ void
151zfcp_qdio_free_queues(struct zfcp_adapter *adapter) 104zfcp_qdio_free_queues(struct zfcp_adapter *adapter)
152{ 105{
153 ZFCP_LOG_TRACE("freeing request_queue buffers\n"); 106 ZFCP_LOG_TRACE("freeing request_queue buffers\n");
154 zfcp_qdio_buffers_dequeue(&(adapter->request_queue.buffer[0]), 107 zfcp_qdio_buffers_dequeue(adapter->request_queue.buffer);
155 QDIO_MAX_BUFFERS_PER_Q);
156 108
157 ZFCP_LOG_TRACE("freeing response_queue buffers\n"); 109 ZFCP_LOG_TRACE("freeing response_queue buffers\n");
158 zfcp_qdio_buffers_dequeue(&(adapter->response_queue.buffer[0]), 110 zfcp_qdio_buffers_dequeue(adapter->response_queue.buffer);
159 QDIO_MAX_BUFFERS_PER_Q);
160} 111}
161 112
162int 113int