diff options
Diffstat (limited to 'drivers/s390/scsi/zfcp_qdio.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_qdio.c | 113 |
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 | */ |
58 | static int | 55 | static void |
59 | zfcp_qdio_buffers_enqueue(struct qdio_buffer **cur_buf, int count) | 56 | zfcp_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 | */ |
98 | static void | 72 | static int |
99 | zfcp_qdio_buffers_dequeue(struct qdio_buffer **cur_buf, int count) | 73 | zfcp_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 */ |
113 | int | 91 | int |
114 | zfcp_qdio_allocate_queues(struct zfcp_adapter *adapter) | 92 | zfcp_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 | |||
151 | zfcp_qdio_free_queues(struct zfcp_adapter *adapter) | 104 | zfcp_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 | ||
162 | int | 113 | int |