diff options
author | David Woodhouse <dwmw2@infradead.org> | 2007-09-21 18:29:36 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.localdomain> | 2007-10-12 14:49:26 -0400 |
commit | d3849d512fb0ca1e369e3efcaec910a949f55f62 (patch) | |
tree | 52b79dd6cd4fe8835ad46b35083edf803c5180b5 /drivers/scsi/ibmvscsi/rpa_vscsi.c | |
parent | 5307b1e8b050f309901acc9c6121061206a70ba5 (diff) |
[SCSI] Fix ibmvscsi client for multiplatform iSeries+pSeries kernel
If you build a multiplatform kernel for iSeries and pSeries, with
ibmvscsic support, the resulting client doesn't work on iSeries.
This fixes that, using the appropriate low-level operations
for the machine detected at runtime.
[jejb: fixed up rejections around the srp transport patch]
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Acked by: Brian King <brking@linux.vnet.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/ibmvscsi/rpa_vscsi.c')
-rw-r--r-- | drivers/scsi/ibmvscsi/rpa_vscsi.c | 113 |
1 files changed, 61 insertions, 52 deletions
diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c index 9c14e789df5f..182146100dc1 100644 --- a/drivers/scsi/ibmvscsi/rpa_vscsi.c +++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c | |||
@@ -42,14 +42,14 @@ static unsigned int partition_number = -1; | |||
42 | * Routines for managing the command/response queue | 42 | * Routines for managing the command/response queue |
43 | */ | 43 | */ |
44 | /** | 44 | /** |
45 | * ibmvscsi_handle_event: - Interrupt handler for crq events | 45 | * rpavscsi_handle_event: - Interrupt handler for crq events |
46 | * @irq: number of irq to handle, not used | 46 | * @irq: number of irq to handle, not used |
47 | * @dev_instance: ibmvscsi_host_data of host that received interrupt | 47 | * @dev_instance: ibmvscsi_host_data of host that received interrupt |
48 | * | 48 | * |
49 | * Disables interrupts and schedules srp_task | 49 | * Disables interrupts and schedules srp_task |
50 | * Always returns IRQ_HANDLED | 50 | * Always returns IRQ_HANDLED |
51 | */ | 51 | */ |
52 | static irqreturn_t ibmvscsi_handle_event(int irq, void *dev_instance) | 52 | static irqreturn_t rpavscsi_handle_event(int irq, void *dev_instance) |
53 | { | 53 | { |
54 | struct ibmvscsi_host_data *hostdata = | 54 | struct ibmvscsi_host_data *hostdata = |
55 | (struct ibmvscsi_host_data *)dev_instance; | 55 | (struct ibmvscsi_host_data *)dev_instance; |
@@ -66,9 +66,9 @@ static irqreturn_t ibmvscsi_handle_event(int irq, void *dev_instance) | |||
66 | * Frees irq, deallocates a page for messages, unmaps dma, and unregisters | 66 | * Frees irq, deallocates a page for messages, unmaps dma, and unregisters |
67 | * the crq with the hypervisor. | 67 | * the crq with the hypervisor. |
68 | */ | 68 | */ |
69 | void ibmvscsi_release_crq_queue(struct crq_queue *queue, | 69 | static void rpavscsi_release_crq_queue(struct crq_queue *queue, |
70 | struct ibmvscsi_host_data *hostdata, | 70 | struct ibmvscsi_host_data *hostdata, |
71 | int max_requests) | 71 | int max_requests) |
72 | { | 72 | { |
73 | long rc; | 73 | long rc; |
74 | struct vio_dev *vdev = to_vio_dev(hostdata->dev); | 74 | struct vio_dev *vdev = to_vio_dev(hostdata->dev); |
@@ -108,12 +108,13 @@ static struct viosrp_crq *crq_queue_next_crq(struct crq_queue *queue) | |||
108 | } | 108 | } |
109 | 109 | ||
110 | /** | 110 | /** |
111 | * ibmvscsi_send_crq: - Send a CRQ | 111 | * rpavscsi_send_crq: - Send a CRQ |
112 | * @hostdata: the adapter | 112 | * @hostdata: the adapter |
113 | * @word1: the first 64 bits of the data | 113 | * @word1: the first 64 bits of the data |
114 | * @word2: the second 64 bits of the data | 114 | * @word2: the second 64 bits of the data |
115 | */ | 115 | */ |
116 | int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2) | 116 | static int rpavscsi_send_crq(struct ibmvscsi_host_data *hostdata, |
117 | u64 word1, u64 word2) | ||
117 | { | 118 | { |
118 | struct vio_dev *vdev = to_vio_dev(hostdata->dev); | 119 | struct vio_dev *vdev = to_vio_dev(hostdata->dev); |
119 | 120 | ||
@@ -121,10 +122,10 @@ int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2) | |||
121 | } | 122 | } |
122 | 123 | ||
123 | /** | 124 | /** |
124 | * ibmvscsi_task: - Process srps asynchronously | 125 | * rpavscsi_task: - Process srps asynchronously |
125 | * @data: ibmvscsi_host_data of host | 126 | * @data: ibmvscsi_host_data of host |
126 | */ | 127 | */ |
127 | static void ibmvscsi_task(void *data) | 128 | static void rpavscsi_task(void *data) |
128 | { | 129 | { |
129 | struct ibmvscsi_host_data *hostdata = (struct ibmvscsi_host_data *)data; | 130 | struct ibmvscsi_host_data *hostdata = (struct ibmvscsi_host_data *)data; |
130 | struct vio_dev *vdev = to_vio_dev(hostdata->dev); | 131 | struct vio_dev *vdev = to_vio_dev(hostdata->dev); |
@@ -190,6 +191,42 @@ static void set_adapter_info(struct ibmvscsi_host_data *hostdata) | |||
190 | } | 191 | } |
191 | 192 | ||
192 | /** | 193 | /** |
194 | * reset_crq_queue: - resets a crq after a failure | ||
195 | * @queue: crq_queue to initialize and register | ||
196 | * @hostdata: ibmvscsi_host_data of host | ||
197 | * | ||
198 | */ | ||
199 | static int rpavscsi_reset_crq_queue(struct crq_queue *queue, | ||
200 | struct ibmvscsi_host_data *hostdata) | ||
201 | { | ||
202 | int rc; | ||
203 | struct vio_dev *vdev = to_vio_dev(hostdata->dev); | ||
204 | |||
205 | /* Close the CRQ */ | ||
206 | do { | ||
207 | rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address); | ||
208 | } while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc))); | ||
209 | |||
210 | /* Clean out the queue */ | ||
211 | memset(queue->msgs, 0x00, PAGE_SIZE); | ||
212 | queue->cur = 0; | ||
213 | |||
214 | set_adapter_info(hostdata); | ||
215 | |||
216 | /* And re-open it again */ | ||
217 | rc = plpar_hcall_norets(H_REG_CRQ, | ||
218 | vdev->unit_address, | ||
219 | queue->msg_token, PAGE_SIZE); | ||
220 | if (rc == 2) { | ||
221 | /* Adapter is good, but other end is not ready */ | ||
222 | dev_warn(hostdata->dev, "Partner adapter not ready\n"); | ||
223 | } else if (rc != 0) { | ||
224 | dev_warn(hostdata->dev, "couldn't register crq--rc 0x%x\n", rc); | ||
225 | } | ||
226 | return rc; | ||
227 | } | ||
228 | |||
229 | /** | ||
193 | * initialize_crq_queue: - Initializes and registers CRQ with hypervisor | 230 | * initialize_crq_queue: - Initializes and registers CRQ with hypervisor |
194 | * @queue: crq_queue to initialize and register | 231 | * @queue: crq_queue to initialize and register |
195 | * @hostdata: ibmvscsi_host_data of host | 232 | * @hostdata: ibmvscsi_host_data of host |
@@ -198,9 +235,9 @@ static void set_adapter_info(struct ibmvscsi_host_data *hostdata) | |||
198 | * the crq with the hypervisor. | 235 | * the crq with the hypervisor. |
199 | * Returns zero on success. | 236 | * Returns zero on success. |
200 | */ | 237 | */ |
201 | int ibmvscsi_init_crq_queue(struct crq_queue *queue, | 238 | static int rpavscsi_init_crq_queue(struct crq_queue *queue, |
202 | struct ibmvscsi_host_data *hostdata, | 239 | struct ibmvscsi_host_data *hostdata, |
203 | int max_requests) | 240 | int max_requests) |
204 | { | 241 | { |
205 | int rc; | 242 | int rc; |
206 | int retrc; | 243 | int retrc; |
@@ -227,7 +264,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue, | |||
227 | queue->msg_token, PAGE_SIZE); | 264 | queue->msg_token, PAGE_SIZE); |
228 | if (rc == H_RESOURCE) | 265 | if (rc == H_RESOURCE) |
229 | /* maybe kexecing and resource is busy. try a reset */ | 266 | /* maybe kexecing and resource is busy. try a reset */ |
230 | rc = ibmvscsi_reset_crq_queue(queue, | 267 | rc = rpavscsi_reset_crq_queue(queue, |
231 | hostdata); | 268 | hostdata); |
232 | 269 | ||
233 | if (rc == 2) { | 270 | if (rc == 2) { |
@@ -240,7 +277,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue, | |||
240 | } | 277 | } |
241 | 278 | ||
242 | if (request_irq(vdev->irq, | 279 | if (request_irq(vdev->irq, |
243 | ibmvscsi_handle_event, | 280 | rpavscsi_handle_event, |
244 | 0, "ibmvscsi", (void *)hostdata) != 0) { | 281 | 0, "ibmvscsi", (void *)hostdata) != 0) { |
245 | dev_err(hostdata->dev, "couldn't register irq 0x%x\n", | 282 | dev_err(hostdata->dev, "couldn't register irq 0x%x\n", |
246 | vdev->irq); | 283 | vdev->irq); |
@@ -256,7 +293,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue, | |||
256 | queue->cur = 0; | 293 | queue->cur = 0; |
257 | spin_lock_init(&queue->lock); | 294 | spin_lock_init(&queue->lock); |
258 | 295 | ||
259 | tasklet_init(&hostdata->srp_task, (void *)ibmvscsi_task, | 296 | tasklet_init(&hostdata->srp_task, (void *)rpavscsi_task, |
260 | (unsigned long)hostdata); | 297 | (unsigned long)hostdata); |
261 | 298 | ||
262 | return retrc; | 299 | return retrc; |
@@ -281,8 +318,8 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue, | |||
281 | * @hostdata: ibmvscsi_host_data of host | 318 | * @hostdata: ibmvscsi_host_data of host |
282 | * | 319 | * |
283 | */ | 320 | */ |
284 | int ibmvscsi_reenable_crq_queue(struct crq_queue *queue, | 321 | static int rpavscsi_reenable_crq_queue(struct crq_queue *queue, |
285 | struct ibmvscsi_host_data *hostdata) | 322 | struct ibmvscsi_host_data *hostdata) |
286 | { | 323 | { |
287 | int rc; | 324 | int rc; |
288 | struct vio_dev *vdev = to_vio_dev(hostdata->dev); | 325 | struct vio_dev *vdev = to_vio_dev(hostdata->dev); |
@@ -297,38 +334,10 @@ int ibmvscsi_reenable_crq_queue(struct crq_queue *queue, | |||
297 | return rc; | 334 | return rc; |
298 | } | 335 | } |
299 | 336 | ||
300 | /** | 337 | struct ibmvscsi_ops rpavscsi_ops = { |
301 | * reset_crq_queue: - resets a crq after a failure | 338 | .init_crq_queue = rpavscsi_init_crq_queue, |
302 | * @queue: crq_queue to initialize and register | 339 | .release_crq_queue = rpavscsi_release_crq_queue, |
303 | * @hostdata: ibmvscsi_host_data of host | 340 | .reset_crq_queue = rpavscsi_reset_crq_queue, |
304 | * | 341 | .reenable_crq_queue = rpavscsi_reenable_crq_queue, |
305 | */ | 342 | .send_crq = rpavscsi_send_crq, |
306 | int ibmvscsi_reset_crq_queue(struct crq_queue *queue, | 343 | }; |
307 | struct ibmvscsi_host_data *hostdata) | ||
308 | { | ||
309 | int rc; | ||
310 | struct vio_dev *vdev = to_vio_dev(hostdata->dev); | ||
311 | |||
312 | /* Close the CRQ */ | ||
313 | do { | ||
314 | rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address); | ||
315 | } while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc))); | ||
316 | |||
317 | /* Clean out the queue */ | ||
318 | memset(queue->msgs, 0x00, PAGE_SIZE); | ||
319 | queue->cur = 0; | ||
320 | |||
321 | set_adapter_info(hostdata); | ||
322 | |||
323 | /* And re-open it again */ | ||
324 | rc = plpar_hcall_norets(H_REG_CRQ, | ||
325 | vdev->unit_address, | ||
326 | queue->msg_token, PAGE_SIZE); | ||
327 | if (rc == 2) { | ||
328 | /* Adapter is good, but other end is not ready */ | ||
329 | dev_warn(hostdata->dev, "Partner adapter not ready\n"); | ||
330 | } else if (rc != 0) { | ||
331 | dev_warn(hostdata->dev, "couldn't register crq--rc 0x%x\n", rc); | ||
332 | } | ||
333 | return rc; | ||
334 | } | ||