diff options
Diffstat (limited to 'drivers/scsi/hptiop.c')
-rw-r--r-- | drivers/scsi/hptiop.c | 593 |
1 files changed, 464 insertions, 129 deletions
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index 0844331abb87..e7b2f3575ce9 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * HighPoint RR3xxx controller driver for Linux | 2 | * HighPoint RR3xxx/4xxx controller driver for Linux |
3 | * Copyright (C) 2006-2007 HighPoint Technologies, Inc. All Rights Reserved. | 3 | * Copyright (C) 2006-2007 HighPoint Technologies, Inc. All Rights Reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
@@ -38,80 +38,84 @@ | |||
38 | #include "hptiop.h" | 38 | #include "hptiop.h" |
39 | 39 | ||
40 | MODULE_AUTHOR("HighPoint Technologies, Inc."); | 40 | MODULE_AUTHOR("HighPoint Technologies, Inc."); |
41 | MODULE_DESCRIPTION("HighPoint RocketRAID 3xxx SATA Controller Driver"); | 41 | MODULE_DESCRIPTION("HighPoint RocketRAID 3xxx/4xxx Controller Driver"); |
42 | 42 | ||
43 | static char driver_name[] = "hptiop"; | 43 | static char driver_name[] = "hptiop"; |
44 | static const char driver_name_long[] = "RocketRAID 3xxx SATA Controller driver"; | 44 | static const char driver_name_long[] = "RocketRAID 3xxx/4xxx Controller driver"; |
45 | static const char driver_ver[] = "v1.2 (070830)"; | 45 | static const char driver_ver[] = "v1.3 (071203)"; |
46 | 46 | ||
47 | static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 tag); | 47 | static int iop_send_sync_msg(struct hptiop_hba *hba, u32 msg, u32 millisec); |
48 | static void hptiop_iop_request_callback(struct hptiop_hba *hba, u32 tag); | 48 | static void hptiop_finish_scsi_req(struct hptiop_hba *hba, u32 tag, |
49 | struct hpt_iop_request_scsi_command *req); | ||
50 | static void hptiop_host_request_callback_itl(struct hptiop_hba *hba, u32 tag); | ||
51 | static void hptiop_iop_request_callback_itl(struct hptiop_hba *hba, u32 tag); | ||
49 | static void hptiop_message_callback(struct hptiop_hba *hba, u32 msg); | 52 | static void hptiop_message_callback(struct hptiop_hba *hba, u32 msg); |
50 | 53 | ||
51 | static inline void hptiop_pci_posting_flush(struct hpt_iopmu __iomem *iop) | 54 | static int iop_wait_ready_itl(struct hptiop_hba *hba, u32 millisec) |
52 | { | ||
53 | readl(&iop->outbound_intstatus); | ||
54 | } | ||
55 | |||
56 | static int iop_wait_ready(struct hpt_iopmu __iomem *iop, u32 millisec) | ||
57 | { | 55 | { |
58 | u32 req = 0; | 56 | u32 req = 0; |
59 | int i; | 57 | int i; |
60 | 58 | ||
61 | for (i = 0; i < millisec; i++) { | 59 | for (i = 0; i < millisec; i++) { |
62 | req = readl(&iop->inbound_queue); | 60 | req = readl(&hba->u.itl.iop->inbound_queue); |
63 | if (req != IOPMU_QUEUE_EMPTY) | 61 | if (req != IOPMU_QUEUE_EMPTY) |
64 | break; | 62 | break; |
65 | msleep(1); | 63 | msleep(1); |
66 | } | 64 | } |
67 | 65 | ||
68 | if (req != IOPMU_QUEUE_EMPTY) { | 66 | if (req != IOPMU_QUEUE_EMPTY) { |
69 | writel(req, &iop->outbound_queue); | 67 | writel(req, &hba->u.itl.iop->outbound_queue); |
70 | hptiop_pci_posting_flush(iop); | 68 | readl(&hba->u.itl.iop->outbound_intstatus); |
71 | return 0; | 69 | return 0; |
72 | } | 70 | } |
73 | 71 | ||
74 | return -1; | 72 | return -1; |
75 | } | 73 | } |
76 | 74 | ||
77 | static void hptiop_request_callback(struct hptiop_hba *hba, u32 tag) | 75 | static int iop_wait_ready_mv(struct hptiop_hba *hba, u32 millisec) |
76 | { | ||
77 | return iop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_NOP, millisec); | ||
78 | } | ||
79 | |||
80 | static void hptiop_request_callback_itl(struct hptiop_hba *hba, u32 tag) | ||
78 | { | 81 | { |
79 | if (tag & IOPMU_QUEUE_ADDR_HOST_BIT) | 82 | if (tag & IOPMU_QUEUE_ADDR_HOST_BIT) |
80 | return hptiop_host_request_callback(hba, | 83 | hptiop_host_request_callback_itl(hba, |
81 | tag & ~IOPMU_QUEUE_ADDR_HOST_BIT); | 84 | tag & ~IOPMU_QUEUE_ADDR_HOST_BIT); |
82 | else | 85 | else |
83 | return hptiop_iop_request_callback(hba, tag); | 86 | hptiop_iop_request_callback_itl(hba, tag); |
84 | } | 87 | } |
85 | 88 | ||
86 | static inline void hptiop_drain_outbound_queue(struct hptiop_hba *hba) | 89 | static void hptiop_drain_outbound_queue_itl(struct hptiop_hba *hba) |
87 | { | 90 | { |
88 | u32 req; | 91 | u32 req; |
89 | 92 | ||
90 | while ((req = readl(&hba->iop->outbound_queue)) != IOPMU_QUEUE_EMPTY) { | 93 | while ((req = readl(&hba->u.itl.iop->outbound_queue)) != |
94 | IOPMU_QUEUE_EMPTY) { | ||
91 | 95 | ||
92 | if (req & IOPMU_QUEUE_MASK_HOST_BITS) | 96 | if (req & IOPMU_QUEUE_MASK_HOST_BITS) |
93 | hptiop_request_callback(hba, req); | 97 | hptiop_request_callback_itl(hba, req); |
94 | else { | 98 | else { |
95 | struct hpt_iop_request_header __iomem * p; | 99 | struct hpt_iop_request_header __iomem * p; |
96 | 100 | ||
97 | p = (struct hpt_iop_request_header __iomem *) | 101 | p = (struct hpt_iop_request_header __iomem *) |
98 | ((char __iomem *)hba->iop + req); | 102 | ((char __iomem *)hba->u.itl.iop + req); |
99 | 103 | ||
100 | if (readl(&p->flags) & IOP_REQUEST_FLAG_SYNC_REQUEST) { | 104 | if (readl(&p->flags) & IOP_REQUEST_FLAG_SYNC_REQUEST) { |
101 | if (readl(&p->context)) | 105 | if (readl(&p->context)) |
102 | hptiop_request_callback(hba, req); | 106 | hptiop_request_callback_itl(hba, req); |
103 | else | 107 | else |
104 | writel(1, &p->context); | 108 | writel(1, &p->context); |
105 | } | 109 | } |
106 | else | 110 | else |
107 | hptiop_request_callback(hba, req); | 111 | hptiop_request_callback_itl(hba, req); |
108 | } | 112 | } |
109 | } | 113 | } |
110 | } | 114 | } |
111 | 115 | ||
112 | static int __iop_intr(struct hptiop_hba *hba) | 116 | static int iop_intr_itl(struct hptiop_hba *hba) |
113 | { | 117 | { |
114 | struct hpt_iopmu __iomem *iop = hba->iop; | 118 | struct hpt_iopmu_itl __iomem *iop = hba->u.itl.iop; |
115 | u32 status; | 119 | u32 status; |
116 | int ret = 0; | 120 | int ret = 0; |
117 | 121 | ||
@@ -119,6 +123,7 @@ static int __iop_intr(struct hptiop_hba *hba) | |||
119 | 123 | ||
120 | if (status & IOPMU_OUTBOUND_INT_MSG0) { | 124 | if (status & IOPMU_OUTBOUND_INT_MSG0) { |
121 | u32 msg = readl(&iop->outbound_msgaddr0); | 125 | u32 msg = readl(&iop->outbound_msgaddr0); |
126 | |||
122 | dprintk("received outbound msg %x\n", msg); | 127 | dprintk("received outbound msg %x\n", msg); |
123 | writel(IOPMU_OUTBOUND_INT_MSG0, &iop->outbound_intstatus); | 128 | writel(IOPMU_OUTBOUND_INT_MSG0, &iop->outbound_intstatus); |
124 | hptiop_message_callback(hba, msg); | 129 | hptiop_message_callback(hba, msg); |
@@ -126,31 +131,115 @@ static int __iop_intr(struct hptiop_hba *hba) | |||
126 | } | 131 | } |
127 | 132 | ||
128 | if (status & IOPMU_OUTBOUND_INT_POSTQUEUE) { | 133 | if (status & IOPMU_OUTBOUND_INT_POSTQUEUE) { |
129 | hptiop_drain_outbound_queue(hba); | 134 | hptiop_drain_outbound_queue_itl(hba); |
135 | ret = 1; | ||
136 | } | ||
137 | |||
138 | return ret; | ||
139 | } | ||
140 | |||
141 | static u64 mv_outbound_read(struct hpt_iopmu_mv __iomem *mu) | ||
142 | { | ||
143 | u32 outbound_tail = readl(&mu->outbound_tail); | ||
144 | u32 outbound_head = readl(&mu->outbound_head); | ||
145 | |||
146 | if (outbound_tail != outbound_head) { | ||
147 | u64 p; | ||
148 | |||
149 | memcpy_fromio(&p, &mu->outbound_q[mu->outbound_tail], 8); | ||
150 | outbound_tail++; | ||
151 | |||
152 | if (outbound_tail == MVIOP_QUEUE_LEN) | ||
153 | outbound_tail = 0; | ||
154 | writel(outbound_tail, &mu->outbound_tail); | ||
155 | return p; | ||
156 | } else | ||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static void mv_inbound_write(u64 p, struct hptiop_hba *hba) | ||
161 | { | ||
162 | u32 inbound_head = readl(&hba->u.mv.mu->inbound_head); | ||
163 | u32 head = inbound_head + 1; | ||
164 | |||
165 | if (head == MVIOP_QUEUE_LEN) | ||
166 | head = 0; | ||
167 | |||
168 | memcpy_toio(&hba->u.mv.mu->inbound_q[inbound_head], &p, 8); | ||
169 | writel(head, &hba->u.mv.mu->inbound_head); | ||
170 | writel(MVIOP_MU_INBOUND_INT_POSTQUEUE, | ||
171 | &hba->u.mv.regs->inbound_doorbell); | ||
172 | } | ||
173 | |||
174 | static void hptiop_request_callback_mv(struct hptiop_hba *hba, u64 tag) | ||
175 | { | ||
176 | u32 req_type = (tag >> 5) & 0x7; | ||
177 | struct hpt_iop_request_scsi_command *req; | ||
178 | |||
179 | dprintk("hptiop_request_callback_mv: tag=%llx\n", tag); | ||
180 | |||
181 | BUG_ON((tag & MVIOP_MU_QUEUE_REQUEST_RETURN_CONTEXT) == 0); | ||
182 | |||
183 | switch (req_type) { | ||
184 | case IOP_REQUEST_TYPE_GET_CONFIG: | ||
185 | case IOP_REQUEST_TYPE_SET_CONFIG: | ||
186 | hba->msg_done = 1; | ||
187 | break; | ||
188 | |||
189 | case IOP_REQUEST_TYPE_SCSI_COMMAND: | ||
190 | req = hba->reqs[tag >> 8].req_virt; | ||
191 | if (likely(tag & MVIOP_MU_QUEUE_REQUEST_RESULT_BIT)) | ||
192 | req->header.result = cpu_to_le32(IOP_RESULT_SUCCESS); | ||
193 | |||
194 | hptiop_finish_scsi_req(hba, tag>>8, req); | ||
195 | break; | ||
196 | |||
197 | default: | ||
198 | break; | ||
199 | } | ||
200 | } | ||
201 | |||
202 | static int iop_intr_mv(struct hptiop_hba *hba) | ||
203 | { | ||
204 | u32 status; | ||
205 | int ret = 0; | ||
206 | |||
207 | status = readl(&hba->u.mv.regs->outbound_doorbell); | ||
208 | writel(~status, &hba->u.mv.regs->outbound_doorbell); | ||
209 | |||
210 | if (status & MVIOP_MU_OUTBOUND_INT_MSG) { | ||
211 | u32 msg; | ||
212 | msg = readl(&hba->u.mv.mu->outbound_msg); | ||
213 | dprintk("received outbound msg %x\n", msg); | ||
214 | hptiop_message_callback(hba, msg); | ||
215 | ret = 1; | ||
216 | } | ||
217 | |||
218 | if (status & MVIOP_MU_OUTBOUND_INT_POSTQUEUE) { | ||
219 | u64 tag; | ||
220 | |||
221 | while ((tag = mv_outbound_read(hba->u.mv.mu))) | ||
222 | hptiop_request_callback_mv(hba, tag); | ||
130 | ret = 1; | 223 | ret = 1; |
131 | } | 224 | } |
132 | 225 | ||
133 | return ret; | 226 | return ret; |
134 | } | 227 | } |
135 | 228 | ||
136 | static int iop_send_sync_request(struct hptiop_hba *hba, | 229 | static int iop_send_sync_request_itl(struct hptiop_hba *hba, |
137 | void __iomem *_req, u32 millisec) | 230 | void __iomem *_req, u32 millisec) |
138 | { | 231 | { |
139 | struct hpt_iop_request_header __iomem *req = _req; | 232 | struct hpt_iop_request_header __iomem *req = _req; |
140 | u32 i; | 233 | u32 i; |
141 | 234 | ||
142 | writel(readl(&req->flags) | IOP_REQUEST_FLAG_SYNC_REQUEST, | 235 | writel(readl(&req->flags) | IOP_REQUEST_FLAG_SYNC_REQUEST, &req->flags); |
143 | &req->flags); | ||
144 | |||
145 | writel(0, &req->context); | 236 | writel(0, &req->context); |
146 | 237 | writel((unsigned long)req - (unsigned long)hba->u.itl.iop, | |
147 | writel((unsigned long)req - (unsigned long)hba->iop, | 238 | &hba->u.itl.iop->inbound_queue); |
148 | &hba->iop->inbound_queue); | 239 | readl(&hba->u.itl.iop->outbound_intstatus); |
149 | |||
150 | hptiop_pci_posting_flush(hba->iop); | ||
151 | 240 | ||
152 | for (i = 0; i < millisec; i++) { | 241 | for (i = 0; i < millisec; i++) { |
153 | __iop_intr(hba); | 242 | iop_intr_itl(hba); |
154 | if (readl(&req->context)) | 243 | if (readl(&req->context)) |
155 | return 0; | 244 | return 0; |
156 | msleep(1); | 245 | msleep(1); |
@@ -159,19 +248,49 @@ static int iop_send_sync_request(struct hptiop_hba *hba, | |||
159 | return -1; | 248 | return -1; |
160 | } | 249 | } |
161 | 250 | ||
162 | static int iop_send_sync_msg(struct hptiop_hba *hba, u32 msg, u32 millisec) | 251 | static int iop_send_sync_request_mv(struct hptiop_hba *hba, |
252 | u32 size_bits, u32 millisec) | ||
163 | { | 253 | { |
254 | struct hpt_iop_request_header *reqhdr = hba->u.mv.internal_req; | ||
164 | u32 i; | 255 | u32 i; |
165 | 256 | ||
166 | hba->msg_done = 0; | 257 | hba->msg_done = 0; |
258 | reqhdr->flags |= cpu_to_le32(IOP_REQUEST_FLAG_SYNC_REQUEST); | ||
259 | mv_inbound_write(hba->u.mv.internal_req_phy | | ||
260 | MVIOP_MU_QUEUE_ADDR_HOST_BIT | size_bits, hba); | ||
261 | |||
262 | for (i = 0; i < millisec; i++) { | ||
263 | iop_intr_mv(hba); | ||
264 | if (hba->msg_done) | ||
265 | return 0; | ||
266 | msleep(1); | ||
267 | } | ||
268 | return -1; | ||
269 | } | ||
270 | |||
271 | static void hptiop_post_msg_itl(struct hptiop_hba *hba, u32 msg) | ||
272 | { | ||
273 | writel(msg, &hba->u.itl.iop->inbound_msgaddr0); | ||
274 | readl(&hba->u.itl.iop->outbound_intstatus); | ||
275 | } | ||
276 | |||
277 | static void hptiop_post_msg_mv(struct hptiop_hba *hba, u32 msg) | ||
278 | { | ||
279 | writel(msg, &hba->u.mv.mu->inbound_msg); | ||
280 | writel(MVIOP_MU_INBOUND_INT_MSG, &hba->u.mv.regs->inbound_doorbell); | ||
281 | readl(&hba->u.mv.regs->inbound_doorbell); | ||
282 | } | ||
167 | 283 | ||
168 | writel(msg, &hba->iop->inbound_msgaddr0); | 284 | static int iop_send_sync_msg(struct hptiop_hba *hba, u32 msg, u32 millisec) |
285 | { | ||
286 | u32 i; | ||
169 | 287 | ||
170 | hptiop_pci_posting_flush(hba->iop); | 288 | hba->msg_done = 0; |
289 | hba->ops->post_msg(hba, msg); | ||
171 | 290 | ||
172 | for (i = 0; i < millisec; i++) { | 291 | for (i = 0; i < millisec; i++) { |
173 | spin_lock_irq(hba->host->host_lock); | 292 | spin_lock_irq(hba->host->host_lock); |
174 | __iop_intr(hba); | 293 | hba->ops->iop_intr(hba); |
175 | spin_unlock_irq(hba->host->host_lock); | 294 | spin_unlock_irq(hba->host->host_lock); |
176 | if (hba->msg_done) | 295 | if (hba->msg_done) |
177 | break; | 296 | break; |
@@ -181,46 +300,67 @@ static int iop_send_sync_msg(struct hptiop_hba *hba, u32 msg, u32 millisec) | |||
181 | return hba->msg_done? 0 : -1; | 300 | return hba->msg_done? 0 : -1; |
182 | } | 301 | } |
183 | 302 | ||
184 | static int iop_get_config(struct hptiop_hba *hba, | 303 | static int iop_get_config_itl(struct hptiop_hba *hba, |
185 | struct hpt_iop_request_get_config *config) | 304 | struct hpt_iop_request_get_config *config) |
186 | { | 305 | { |
187 | u32 req32; | 306 | u32 req32; |
188 | struct hpt_iop_request_get_config __iomem *req; | 307 | struct hpt_iop_request_get_config __iomem *req; |
189 | 308 | ||
190 | req32 = readl(&hba->iop->inbound_queue); | 309 | req32 = readl(&hba->u.itl.iop->inbound_queue); |
191 | if (req32 == IOPMU_QUEUE_EMPTY) | 310 | if (req32 == IOPMU_QUEUE_EMPTY) |
192 | return -1; | 311 | return -1; |
193 | 312 | ||
194 | req = (struct hpt_iop_request_get_config __iomem *) | 313 | req = (struct hpt_iop_request_get_config __iomem *) |
195 | ((unsigned long)hba->iop + req32); | 314 | ((unsigned long)hba->u.itl.iop + req32); |
196 | 315 | ||
197 | writel(0, &req->header.flags); | 316 | writel(0, &req->header.flags); |
198 | writel(IOP_REQUEST_TYPE_GET_CONFIG, &req->header.type); | 317 | writel(IOP_REQUEST_TYPE_GET_CONFIG, &req->header.type); |
199 | writel(sizeof(struct hpt_iop_request_get_config), &req->header.size); | 318 | writel(sizeof(struct hpt_iop_request_get_config), &req->header.size); |
200 | writel(IOP_RESULT_PENDING, &req->header.result); | 319 | writel(IOP_RESULT_PENDING, &req->header.result); |
201 | 320 | ||
202 | if (iop_send_sync_request(hba, req, 20000)) { | 321 | if (iop_send_sync_request_itl(hba, req, 20000)) { |
203 | dprintk("Get config send cmd failed\n"); | 322 | dprintk("Get config send cmd failed\n"); |
204 | return -1; | 323 | return -1; |
205 | } | 324 | } |
206 | 325 | ||
207 | memcpy_fromio(config, req, sizeof(*config)); | 326 | memcpy_fromio(config, req, sizeof(*config)); |
208 | writel(req32, &hba->iop->outbound_queue); | 327 | writel(req32, &hba->u.itl.iop->outbound_queue); |
328 | return 0; | ||
329 | } | ||
330 | |||
331 | static int iop_get_config_mv(struct hptiop_hba *hba, | ||
332 | struct hpt_iop_request_get_config *config) | ||
333 | { | ||
334 | struct hpt_iop_request_get_config *req = hba->u.mv.internal_req; | ||
335 | |||
336 | req->header.flags = cpu_to_le32(IOP_REQUEST_FLAG_OUTPUT_CONTEXT); | ||
337 | req->header.type = cpu_to_le32(IOP_REQUEST_TYPE_GET_CONFIG); | ||
338 | req->header.size = | ||
339 | cpu_to_le32(sizeof(struct hpt_iop_request_get_config)); | ||
340 | req->header.result = cpu_to_le32(IOP_RESULT_PENDING); | ||
341 | req->header.context = cpu_to_le64(IOP_REQUEST_TYPE_GET_CONFIG<<5); | ||
342 | |||
343 | if (iop_send_sync_request_mv(hba, 0, 20000)) { | ||
344 | dprintk("Get config send cmd failed\n"); | ||
345 | return -1; | ||
346 | } | ||
347 | |||
348 | memcpy(config, req, sizeof(struct hpt_iop_request_get_config)); | ||
209 | return 0; | 349 | return 0; |
210 | } | 350 | } |
211 | 351 | ||
212 | static int iop_set_config(struct hptiop_hba *hba, | 352 | static int iop_set_config_itl(struct hptiop_hba *hba, |
213 | struct hpt_iop_request_set_config *config) | 353 | struct hpt_iop_request_set_config *config) |
214 | { | 354 | { |
215 | u32 req32; | 355 | u32 req32; |
216 | struct hpt_iop_request_set_config __iomem *req; | 356 | struct hpt_iop_request_set_config __iomem *req; |
217 | 357 | ||
218 | req32 = readl(&hba->iop->inbound_queue); | 358 | req32 = readl(&hba->u.itl.iop->inbound_queue); |
219 | if (req32 == IOPMU_QUEUE_EMPTY) | 359 | if (req32 == IOPMU_QUEUE_EMPTY) |
220 | return -1; | 360 | return -1; |
221 | 361 | ||
222 | req = (struct hpt_iop_request_set_config __iomem *) | 362 | req = (struct hpt_iop_request_set_config __iomem *) |
223 | ((unsigned long)hba->iop + req32); | 363 | ((unsigned long)hba->u.itl.iop + req32); |
224 | 364 | ||
225 | memcpy_toio((u8 __iomem *)req + sizeof(struct hpt_iop_request_header), | 365 | memcpy_toio((u8 __iomem *)req + sizeof(struct hpt_iop_request_header), |
226 | (u8 *)config + sizeof(struct hpt_iop_request_header), | 366 | (u8 *)config + sizeof(struct hpt_iop_request_header), |
@@ -232,22 +372,52 @@ static int iop_set_config(struct hptiop_hba *hba, | |||
232 | writel(sizeof(struct hpt_iop_request_set_config), &req->header.size); | 372 | writel(sizeof(struct hpt_iop_request_set_config), &req->header.size); |
233 | writel(IOP_RESULT_PENDING, &req->header.result); | 373 | writel(IOP_RESULT_PENDING, &req->header.result); |
234 | 374 | ||
235 | if (iop_send_sync_request(hba, req, 20000)) { | 375 | if (iop_send_sync_request_itl(hba, req, 20000)) { |
236 | dprintk("Set config send cmd failed\n"); | 376 | dprintk("Set config send cmd failed\n"); |
237 | return -1; | 377 | return -1; |
238 | } | 378 | } |
239 | 379 | ||
240 | writel(req32, &hba->iop->outbound_queue); | 380 | writel(req32, &hba->u.itl.iop->outbound_queue); |
241 | return 0; | 381 | return 0; |
242 | } | 382 | } |
243 | 383 | ||
244 | static int hptiop_initialize_iop(struct hptiop_hba *hba) | 384 | static int iop_set_config_mv(struct hptiop_hba *hba, |
385 | struct hpt_iop_request_set_config *config) | ||
245 | { | 386 | { |
246 | struct hpt_iopmu __iomem *iop = hba->iop; | 387 | struct hpt_iop_request_set_config *req = hba->u.mv.internal_req; |
247 | 388 | ||
248 | /* enable interrupts */ | 389 | memcpy(req, config, sizeof(struct hpt_iop_request_set_config)); |
390 | req->header.flags = cpu_to_le32(IOP_REQUEST_FLAG_OUTPUT_CONTEXT); | ||
391 | req->header.type = cpu_to_le32(IOP_REQUEST_TYPE_SET_CONFIG); | ||
392 | req->header.size = | ||
393 | cpu_to_le32(sizeof(struct hpt_iop_request_set_config)); | ||
394 | req->header.result = cpu_to_le32(IOP_RESULT_PENDING); | ||
395 | req->header.context = cpu_to_le64(IOP_REQUEST_TYPE_SET_CONFIG<<5); | ||
396 | |||
397 | if (iop_send_sync_request_mv(hba, 0, 20000)) { | ||
398 | dprintk("Set config send cmd failed\n"); | ||
399 | return -1; | ||
400 | } | ||
401 | |||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | static void hptiop_enable_intr_itl(struct hptiop_hba *hba) | ||
406 | { | ||
249 | writel(~(IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0), | 407 | writel(~(IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0), |
250 | &iop->outbound_intmask); | 408 | &hba->u.itl.iop->outbound_intmask); |
409 | } | ||
410 | |||
411 | static void hptiop_enable_intr_mv(struct hptiop_hba *hba) | ||
412 | { | ||
413 | writel(MVIOP_MU_OUTBOUND_INT_POSTQUEUE | MVIOP_MU_OUTBOUND_INT_MSG, | ||
414 | &hba->u.mv.regs->outbound_intmask); | ||
415 | } | ||
416 | |||
417 | static int hptiop_initialize_iop(struct hptiop_hba *hba) | ||
418 | { | ||
419 | /* enable interrupts */ | ||
420 | hba->ops->enable_intr(hba); | ||
251 | 421 | ||
252 | hba->initialized = 1; | 422 | hba->initialized = 1; |
253 | 423 | ||
@@ -261,37 +431,74 @@ static int hptiop_initialize_iop(struct hptiop_hba *hba) | |||
261 | return 0; | 431 | return 0; |
262 | } | 432 | } |
263 | 433 | ||
264 | static int hptiop_map_pci_bar(struct hptiop_hba *hba) | 434 | static void __iomem *hptiop_map_pci_bar(struct hptiop_hba *hba, int index) |
265 | { | 435 | { |
266 | u32 mem_base_phy, length; | 436 | u32 mem_base_phy, length; |
267 | void __iomem *mem_base_virt; | 437 | void __iomem *mem_base_virt; |
438 | |||
268 | struct pci_dev *pcidev = hba->pcidev; | 439 | struct pci_dev *pcidev = hba->pcidev; |
269 | 440 | ||
270 | if (!(pci_resource_flags(pcidev, 0) & IORESOURCE_MEM)) { | 441 | |
442 | if (!(pci_resource_flags(pcidev, index) & IORESOURCE_MEM)) { | ||
271 | printk(KERN_ERR "scsi%d: pci resource invalid\n", | 443 | printk(KERN_ERR "scsi%d: pci resource invalid\n", |
272 | hba->host->host_no); | 444 | hba->host->host_no); |
273 | return -1; | 445 | return 0; |
274 | } | 446 | } |
275 | 447 | ||
276 | mem_base_phy = pci_resource_start(pcidev, 0); | 448 | mem_base_phy = pci_resource_start(pcidev, index); |
277 | length = pci_resource_len(pcidev, 0); | 449 | length = pci_resource_len(pcidev, index); |
278 | mem_base_virt = ioremap(mem_base_phy, length); | 450 | mem_base_virt = ioremap(mem_base_phy, length); |
279 | 451 | ||
280 | if (!mem_base_virt) { | 452 | if (!mem_base_virt) { |
281 | printk(KERN_ERR "scsi%d: Fail to ioremap memory space\n", | 453 | printk(KERN_ERR "scsi%d: Fail to ioremap memory space\n", |
282 | hba->host->host_no); | 454 | hba->host->host_no); |
455 | return 0; | ||
456 | } | ||
457 | return mem_base_virt; | ||
458 | } | ||
459 | |||
460 | static int hptiop_map_pci_bar_itl(struct hptiop_hba *hba) | ||
461 | { | ||
462 | hba->u.itl.iop = hptiop_map_pci_bar(hba, 0); | ||
463 | if (hba->u.itl.iop) | ||
464 | return 0; | ||
465 | else | ||
466 | return -1; | ||
467 | } | ||
468 | |||
469 | static void hptiop_unmap_pci_bar_itl(struct hptiop_hba *hba) | ||
470 | { | ||
471 | iounmap(hba->u.itl.iop); | ||
472 | } | ||
473 | |||
474 | static int hptiop_map_pci_bar_mv(struct hptiop_hba *hba) | ||
475 | { | ||
476 | hba->u.mv.regs = hptiop_map_pci_bar(hba, 0); | ||
477 | if (hba->u.mv.regs == 0) | ||
478 | return -1; | ||
479 | |||
480 | hba->u.mv.mu = hptiop_map_pci_bar(hba, 2); | ||
481 | if (hba->u.mv.mu == 0) { | ||
482 | iounmap(hba->u.mv.regs); | ||
283 | return -1; | 483 | return -1; |
284 | } | 484 | } |
285 | 485 | ||
286 | hba->iop = mem_base_virt; | ||
287 | dprintk("hptiop_map_pci_bar: iop=%p\n", hba->iop); | ||
288 | return 0; | 486 | return 0; |
289 | } | 487 | } |
290 | 488 | ||
489 | static void hptiop_unmap_pci_bar_mv(struct hptiop_hba *hba) | ||
490 | { | ||
491 | iounmap(hba->u.mv.regs); | ||
492 | iounmap(hba->u.mv.mu); | ||
493 | } | ||
494 | |||
291 | static void hptiop_message_callback(struct hptiop_hba *hba, u32 msg) | 495 | static void hptiop_message_callback(struct hptiop_hba *hba, u32 msg) |
292 | { | 496 | { |
293 | dprintk("iop message 0x%x\n", msg); | 497 | dprintk("iop message 0x%x\n", msg); |
294 | 498 | ||
499 | if (msg == IOPMU_INBOUND_MSG0_NOP) | ||
500 | hba->msg_done = 1; | ||
501 | |||
295 | if (!hba->initialized) | 502 | if (!hba->initialized) |
296 | return; | 503 | return; |
297 | 504 | ||
@@ -303,7 +510,7 @@ static void hptiop_message_callback(struct hptiop_hba *hba, u32 msg) | |||
303 | hba->msg_done = 1; | 510 | hba->msg_done = 1; |
304 | } | 511 | } |
305 | 512 | ||
306 | static inline struct hptiop_request *get_req(struct hptiop_hba *hba) | 513 | static struct hptiop_request *get_req(struct hptiop_hba *hba) |
307 | { | 514 | { |
308 | struct hptiop_request *ret; | 515 | struct hptiop_request *ret; |
309 | 516 | ||
@@ -316,30 +523,19 @@ static inline struct hptiop_request *get_req(struct hptiop_hba *hba) | |||
316 | return ret; | 523 | return ret; |
317 | } | 524 | } |
318 | 525 | ||
319 | static inline void free_req(struct hptiop_hba *hba, struct hptiop_request *req) | 526 | static void free_req(struct hptiop_hba *hba, struct hptiop_request *req) |
320 | { | 527 | { |
321 | dprintk("free_req(%d, %p)\n", req->index, req); | 528 | dprintk("free_req(%d, %p)\n", req->index, req); |
322 | req->next = hba->req_list; | 529 | req->next = hba->req_list; |
323 | hba->req_list = req; | 530 | hba->req_list = req; |
324 | } | 531 | } |
325 | 532 | ||
326 | static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 _tag) | 533 | static void hptiop_finish_scsi_req(struct hptiop_hba *hba, u32 tag, |
534 | struct hpt_iop_request_scsi_command *req) | ||
327 | { | 535 | { |
328 | struct hpt_iop_request_scsi_command *req; | ||
329 | struct scsi_cmnd *scp; | 536 | struct scsi_cmnd *scp; |
330 | u32 tag; | ||
331 | |||
332 | if (hba->iopintf_v2) { | ||
333 | tag = _tag & ~ IOPMU_QUEUE_REQUEST_RESULT_BIT; | ||
334 | req = hba->reqs[tag].req_virt; | ||
335 | if (likely(_tag & IOPMU_QUEUE_REQUEST_RESULT_BIT)) | ||
336 | req->header.result = IOP_RESULT_SUCCESS; | ||
337 | } else { | ||
338 | tag = _tag; | ||
339 | req = hba->reqs[tag].req_virt; | ||
340 | } | ||
341 | 537 | ||
342 | dprintk("hptiop_host_request_callback: req=%p, type=%d, " | 538 | dprintk("hptiop_finish_scsi_req: req=%p, type=%d, " |
343 | "result=%d, context=0x%x tag=%d\n", | 539 | "result=%d, context=0x%x tag=%d\n", |
344 | req, req->header.type, req->header.result, | 540 | req, req->header.type, req->header.result, |
345 | req->header.context, tag); | 541 | req->header.context, tag); |
@@ -354,6 +550,8 @@ static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 _tag) | |||
354 | 550 | ||
355 | switch (le32_to_cpu(req->header.result)) { | 551 | switch (le32_to_cpu(req->header.result)) { |
356 | case IOP_RESULT_SUCCESS: | 552 | case IOP_RESULT_SUCCESS: |
553 | scsi_set_resid(scp, | ||
554 | scsi_bufflen(scp) - le32_to_cpu(req->dataxfer_length)); | ||
357 | scp->result = (DID_OK<<16); | 555 | scp->result = (DID_OK<<16); |
358 | break; | 556 | break; |
359 | case IOP_RESULT_BAD_TARGET: | 557 | case IOP_RESULT_BAD_TARGET: |
@@ -371,12 +569,12 @@ static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 _tag) | |||
371 | case IOP_RESULT_INVALID_REQUEST: | 569 | case IOP_RESULT_INVALID_REQUEST: |
372 | scp->result = (DID_ABORT<<16); | 570 | scp->result = (DID_ABORT<<16); |
373 | break; | 571 | break; |
374 | case IOP_RESULT_MODE_SENSE_CHECK_CONDITION: | 572 | case IOP_RESULT_CHECK_CONDITION: |
573 | scsi_set_resid(scp, | ||
574 | scsi_bufflen(scp) - le32_to_cpu(req->dataxfer_length)); | ||
375 | scp->result = SAM_STAT_CHECK_CONDITION; | 575 | scp->result = SAM_STAT_CHECK_CONDITION; |
376 | memset(&scp->sense_buffer, | ||
377 | 0, sizeof(scp->sense_buffer)); | ||
378 | memcpy(&scp->sense_buffer, &req->sg_list, | 576 | memcpy(&scp->sense_buffer, &req->sg_list, |
379 | min(sizeof(scp->sense_buffer), | 577 | min_t(size_t, SCSI_SENSE_BUFFERSIZE, |
380 | le32_to_cpu(req->dataxfer_length))); | 578 | le32_to_cpu(req->dataxfer_length))); |
381 | break; | 579 | break; |
382 | 580 | ||
@@ -391,15 +589,33 @@ static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 _tag) | |||
391 | free_req(hba, &hba->reqs[tag]); | 589 | free_req(hba, &hba->reqs[tag]); |
392 | } | 590 | } |
393 | 591 | ||
394 | void hptiop_iop_request_callback(struct hptiop_hba *hba, u32 tag) | 592 | static void hptiop_host_request_callback_itl(struct hptiop_hba *hba, u32 _tag) |
593 | { | ||
594 | struct hpt_iop_request_scsi_command *req; | ||
595 | u32 tag; | ||
596 | |||
597 | if (hba->iopintf_v2) { | ||
598 | tag = _tag & ~IOPMU_QUEUE_REQUEST_RESULT_BIT; | ||
599 | req = hba->reqs[tag].req_virt; | ||
600 | if (likely(_tag & IOPMU_QUEUE_REQUEST_RESULT_BIT)) | ||
601 | req->header.result = cpu_to_le32(IOP_RESULT_SUCCESS); | ||
602 | } else { | ||
603 | tag = _tag; | ||
604 | req = hba->reqs[tag].req_virt; | ||
605 | } | ||
606 | |||
607 | hptiop_finish_scsi_req(hba, tag, req); | ||
608 | } | ||
609 | |||
610 | void hptiop_iop_request_callback_itl(struct hptiop_hba *hba, u32 tag) | ||
395 | { | 611 | { |
396 | struct hpt_iop_request_header __iomem *req; | 612 | struct hpt_iop_request_header __iomem *req; |
397 | struct hpt_iop_request_ioctl_command __iomem *p; | 613 | struct hpt_iop_request_ioctl_command __iomem *p; |
398 | struct hpt_ioctl_k *arg; | 614 | struct hpt_ioctl_k *arg; |
399 | 615 | ||
400 | req = (struct hpt_iop_request_header __iomem *) | 616 | req = (struct hpt_iop_request_header __iomem *) |
401 | ((unsigned long)hba->iop + tag); | 617 | ((unsigned long)hba->u.itl.iop + tag); |
402 | dprintk("hptiop_iop_request_callback: req=%p, type=%d, " | 618 | dprintk("hptiop_iop_request_callback_itl: req=%p, type=%d, " |
403 | "result=%d, context=0x%x tag=%d\n", | 619 | "result=%d, context=0x%x tag=%d\n", |
404 | req, readl(&req->type), readl(&req->result), | 620 | req, readl(&req->type), readl(&req->result), |
405 | readl(&req->context), tag); | 621 | readl(&req->context), tag); |
@@ -427,7 +643,7 @@ void hptiop_iop_request_callback(struct hptiop_hba *hba, u32 tag) | |||
427 | arg->result = HPT_IOCTL_RESULT_FAILED; | 643 | arg->result = HPT_IOCTL_RESULT_FAILED; |
428 | 644 | ||
429 | arg->done(arg); | 645 | arg->done(arg); |
430 | writel(tag, &hba->iop->outbound_queue); | 646 | writel(tag, &hba->u.itl.iop->outbound_queue); |
431 | } | 647 | } |
432 | 648 | ||
433 | static irqreturn_t hptiop_intr(int irq, void *dev_id) | 649 | static irqreturn_t hptiop_intr(int irq, void *dev_id) |
@@ -437,7 +653,7 @@ static irqreturn_t hptiop_intr(int irq, void *dev_id) | |||
437 | unsigned long flags; | 653 | unsigned long flags; |
438 | 654 | ||
439 | spin_lock_irqsave(hba->host->host_lock, flags); | 655 | spin_lock_irqsave(hba->host->host_lock, flags); |
440 | handled = __iop_intr(hba); | 656 | handled = hba->ops->iop_intr(hba); |
441 | spin_unlock_irqrestore(hba->host->host_lock, flags); | 657 | spin_unlock_irqrestore(hba->host->host_lock, flags); |
442 | 658 | ||
443 | return handled; | 659 | return handled; |
@@ -469,6 +685,57 @@ static int hptiop_buildsgl(struct scsi_cmnd *scp, struct hpt_iopsg *psg) | |||
469 | return HPT_SCP(scp)->sgcnt; | 685 | return HPT_SCP(scp)->sgcnt; |
470 | } | 686 | } |
471 | 687 | ||
688 | static void hptiop_post_req_itl(struct hptiop_hba *hba, | ||
689 | struct hptiop_request *_req) | ||
690 | { | ||
691 | struct hpt_iop_request_header *reqhdr = _req->req_virt; | ||
692 | |||
693 | reqhdr->context = cpu_to_le32(IOPMU_QUEUE_ADDR_HOST_BIT | | ||
694 | (u32)_req->index); | ||
695 | reqhdr->context_hi32 = 0; | ||
696 | |||
697 | if (hba->iopintf_v2) { | ||
698 | u32 size, size_bits; | ||
699 | |||
700 | size = le32_to_cpu(reqhdr->size); | ||
701 | if (size < 256) | ||
702 | size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT; | ||
703 | else if (size < 512) | ||
704 | size_bits = IOPMU_QUEUE_ADDR_HOST_BIT; | ||
705 | else | ||
706 | size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT | | ||
707 | IOPMU_QUEUE_ADDR_HOST_BIT; | ||
708 | writel(_req->req_shifted_phy | size_bits, | ||
709 | &hba->u.itl.iop->inbound_queue); | ||
710 | } else | ||
711 | writel(_req->req_shifted_phy | IOPMU_QUEUE_ADDR_HOST_BIT, | ||
712 | &hba->u.itl.iop->inbound_queue); | ||
713 | } | ||
714 | |||
715 | static void hptiop_post_req_mv(struct hptiop_hba *hba, | ||
716 | struct hptiop_request *_req) | ||
717 | { | ||
718 | struct hpt_iop_request_header *reqhdr = _req->req_virt; | ||
719 | u32 size, size_bit; | ||
720 | |||
721 | reqhdr->context = cpu_to_le32(_req->index<<8 | | ||
722 | IOP_REQUEST_TYPE_SCSI_COMMAND<<5); | ||
723 | reqhdr->context_hi32 = 0; | ||
724 | size = le32_to_cpu(reqhdr->size); | ||
725 | |||
726 | if (size <= 256) | ||
727 | size_bit = 0; | ||
728 | else if (size <= 256*2) | ||
729 | size_bit = 1; | ||
730 | else if (size <= 256*3) | ||
731 | size_bit = 2; | ||
732 | else | ||
733 | size_bit = 3; | ||
734 | |||
735 | mv_inbound_write((_req->req_shifted_phy << 5) | | ||
736 | MVIOP_MU_QUEUE_ADDR_HOST_BIT | size_bit, hba); | ||
737 | } | ||
738 | |||
472 | static int hptiop_queuecommand(struct scsi_cmnd *scp, | 739 | static int hptiop_queuecommand(struct scsi_cmnd *scp, |
473 | void (*done)(struct scsi_cmnd *)) | 740 | void (*done)(struct scsi_cmnd *)) |
474 | { | 741 | { |
@@ -518,9 +785,6 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp, | |||
518 | req->header.flags = cpu_to_le32(IOP_REQUEST_FLAG_OUTPUT_CONTEXT); | 785 | req->header.flags = cpu_to_le32(IOP_REQUEST_FLAG_OUTPUT_CONTEXT); |
519 | req->header.type = cpu_to_le32(IOP_REQUEST_TYPE_SCSI_COMMAND); | 786 | req->header.type = cpu_to_le32(IOP_REQUEST_TYPE_SCSI_COMMAND); |
520 | req->header.result = cpu_to_le32(IOP_RESULT_PENDING); | 787 | req->header.result = cpu_to_le32(IOP_RESULT_PENDING); |
521 | req->header.context = cpu_to_le32(IOPMU_QUEUE_ADDR_HOST_BIT | | ||
522 | (u32)_req->index); | ||
523 | req->header.context_hi32 = 0; | ||
524 | req->dataxfer_length = cpu_to_le32(scsi_bufflen(scp)); | 788 | req->dataxfer_length = cpu_to_le32(scsi_bufflen(scp)); |
525 | req->channel = scp->device->channel; | 789 | req->channel = scp->device->channel; |
526 | req->target = scp->device->id; | 790 | req->target = scp->device->id; |
@@ -531,21 +795,7 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp, | |||
531 | + sg_count * sizeof(struct hpt_iopsg)); | 795 | + sg_count * sizeof(struct hpt_iopsg)); |
532 | 796 | ||
533 | memcpy(req->cdb, scp->cmnd, sizeof(req->cdb)); | 797 | memcpy(req->cdb, scp->cmnd, sizeof(req->cdb)); |
534 | 798 | hba->ops->post_req(hba, _req); | |
535 | if (hba->iopintf_v2) { | ||
536 | u32 size_bits; | ||
537 | if (req->header.size < 256) | ||
538 | size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT; | ||
539 | else if (req->header.size < 512) | ||
540 | size_bits = IOPMU_QUEUE_ADDR_HOST_BIT; | ||
541 | else | ||
542 | size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT | | ||
543 | IOPMU_QUEUE_ADDR_HOST_BIT; | ||
544 | writel(_req->req_shifted_phy | size_bits, &hba->iop->inbound_queue); | ||
545 | } else | ||
546 | writel(_req->req_shifted_phy | IOPMU_QUEUE_ADDR_HOST_BIT, | ||
547 | &hba->iop->inbound_queue); | ||
548 | |||
549 | return 0; | 799 | return 0; |
550 | 800 | ||
551 | cmd_done: | 801 | cmd_done: |
@@ -563,9 +813,7 @@ static int hptiop_reset_hba(struct hptiop_hba *hba) | |||
563 | { | 813 | { |
564 | if (atomic_xchg(&hba->resetting, 1) == 0) { | 814 | if (atomic_xchg(&hba->resetting, 1) == 0) { |
565 | atomic_inc(&hba->reset_count); | 815 | atomic_inc(&hba->reset_count); |
566 | writel(IOPMU_INBOUND_MSG0_RESET, | 816 | hba->ops->post_msg(hba, IOPMU_INBOUND_MSG0_RESET); |
567 | &hba->iop->inbound_msgaddr0); | ||
568 | hptiop_pci_posting_flush(hba->iop); | ||
569 | } | 817 | } |
570 | 818 | ||
571 | wait_event_timeout(hba->reset_wq, | 819 | wait_event_timeout(hba->reset_wq, |
@@ -601,8 +849,10 @@ static int hptiop_reset(struct scsi_cmnd *scp) | |||
601 | static int hptiop_adjust_disk_queue_depth(struct scsi_device *sdev, | 849 | static int hptiop_adjust_disk_queue_depth(struct scsi_device *sdev, |
602 | int queue_depth) | 850 | int queue_depth) |
603 | { | 851 | { |
604 | if(queue_depth > 256) | 852 | struct hptiop_hba *hba = (struct hptiop_hba *)sdev->host->hostdata; |
605 | queue_depth = 256; | 853 | |
854 | if (queue_depth > hba->max_requests) | ||
855 | queue_depth = hba->max_requests; | ||
606 | scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth); | 856 | scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth); |
607 | return queue_depth; | 857 | return queue_depth; |
608 | } | 858 | } |
@@ -663,6 +913,26 @@ static struct scsi_host_template driver_template = { | |||
663 | .change_queue_depth = hptiop_adjust_disk_queue_depth, | 913 | .change_queue_depth = hptiop_adjust_disk_queue_depth, |
664 | }; | 914 | }; |
665 | 915 | ||
916 | static int hptiop_internal_memalloc_mv(struct hptiop_hba *hba) | ||
917 | { | ||
918 | hba->u.mv.internal_req = dma_alloc_coherent(&hba->pcidev->dev, | ||
919 | 0x800, &hba->u.mv.internal_req_phy, GFP_KERNEL); | ||
920 | if (hba->u.mv.internal_req) | ||
921 | return 0; | ||
922 | else | ||
923 | return -1; | ||
924 | } | ||
925 | |||
926 | static int hptiop_internal_memfree_mv(struct hptiop_hba *hba) | ||
927 | { | ||
928 | if (hba->u.mv.internal_req) { | ||
929 | dma_free_coherent(&hba->pcidev->dev, 0x800, | ||
930 | hba->u.mv.internal_req, hba->u.mv.internal_req_phy); | ||
931 | return 0; | ||
932 | } else | ||
933 | return -1; | ||
934 | } | ||
935 | |||
666 | static int __devinit hptiop_probe(struct pci_dev *pcidev, | 936 | static int __devinit hptiop_probe(struct pci_dev *pcidev, |
667 | const struct pci_device_id *id) | 937 | const struct pci_device_id *id) |
668 | { | 938 | { |
@@ -708,6 +978,7 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev, | |||
708 | 978 | ||
709 | hba = (struct hptiop_hba *)host->hostdata; | 979 | hba = (struct hptiop_hba *)host->hostdata; |
710 | 980 | ||
981 | hba->ops = (struct hptiop_adapter_ops *)id->driver_data; | ||
711 | hba->pcidev = pcidev; | 982 | hba->pcidev = pcidev; |
712 | hba->host = host; | 983 | hba->host = host; |
713 | hba->initialized = 0; | 984 | hba->initialized = 0; |
@@ -725,16 +996,24 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev, | |||
725 | host->n_io_port = 0; | 996 | host->n_io_port = 0; |
726 | host->irq = pcidev->irq; | 997 | host->irq = pcidev->irq; |
727 | 998 | ||
728 | if (hptiop_map_pci_bar(hba)) | 999 | if (hba->ops->map_pci_bar(hba)) |
729 | goto free_scsi_host; | 1000 | goto free_scsi_host; |
730 | 1001 | ||
731 | if (iop_wait_ready(hba->iop, 20000)) { | 1002 | if (hba->ops->iop_wait_ready(hba, 20000)) { |
732 | printk(KERN_ERR "scsi%d: firmware not ready\n", | 1003 | printk(KERN_ERR "scsi%d: firmware not ready\n", |
733 | hba->host->host_no); | 1004 | hba->host->host_no); |
734 | goto unmap_pci_bar; | 1005 | goto unmap_pci_bar; |
735 | } | 1006 | } |
736 | 1007 | ||
737 | if (iop_get_config(hba, &iop_config)) { | 1008 | if (hba->ops->internal_memalloc) { |
1009 | if (hba->ops->internal_memalloc(hba)) { | ||
1010 | printk(KERN_ERR "scsi%d: internal_memalloc failed\n", | ||
1011 | hba->host->host_no); | ||
1012 | goto unmap_pci_bar; | ||
1013 | } | ||
1014 | } | ||
1015 | |||
1016 | if (hba->ops->get_config(hba, &iop_config)) { | ||
738 | printk(KERN_ERR "scsi%d: get config failed\n", | 1017 | printk(KERN_ERR "scsi%d: get config failed\n", |
739 | hba->host->host_no); | 1018 | hba->host->host_no); |
740 | goto unmap_pci_bar; | 1019 | goto unmap_pci_bar; |
@@ -770,7 +1049,7 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev, | |||
770 | set_config.vbus_id = cpu_to_le16(host->host_no); | 1049 | set_config.vbus_id = cpu_to_le16(host->host_no); |
771 | set_config.max_host_request_size = cpu_to_le16(req_size); | 1050 | set_config.max_host_request_size = cpu_to_le16(req_size); |
772 | 1051 | ||
773 | if (iop_set_config(hba, &set_config)) { | 1052 | if (hba->ops->set_config(hba, &set_config)) { |
774 | printk(KERN_ERR "scsi%d: set config failed\n", | 1053 | printk(KERN_ERR "scsi%d: set config failed\n", |
775 | hba->host->host_no); | 1054 | hba->host->host_no); |
776 | goto unmap_pci_bar; | 1055 | goto unmap_pci_bar; |
@@ -839,21 +1118,24 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev, | |||
839 | 1118 | ||
840 | free_request_mem: | 1119 | free_request_mem: |
841 | dma_free_coherent(&hba->pcidev->dev, | 1120 | dma_free_coherent(&hba->pcidev->dev, |
842 | hba->req_size*hba->max_requests + 0x20, | 1121 | hba->req_size * hba->max_requests + 0x20, |
843 | hba->dma_coherent, hba->dma_coherent_handle); | 1122 | hba->dma_coherent, hba->dma_coherent_handle); |
844 | 1123 | ||
845 | free_request_irq: | 1124 | free_request_irq: |
846 | free_irq(hba->pcidev->irq, hba); | 1125 | free_irq(hba->pcidev->irq, hba); |
847 | 1126 | ||
848 | unmap_pci_bar: | 1127 | unmap_pci_bar: |
849 | iounmap(hba->iop); | 1128 | if (hba->ops->internal_memfree) |
1129 | hba->ops->internal_memfree(hba); | ||
850 | 1130 | ||
851 | free_pci_regions: | 1131 | hba->ops->unmap_pci_bar(hba); |
852 | pci_release_regions(pcidev) ; | ||
853 | 1132 | ||
854 | free_scsi_host: | 1133 | free_scsi_host: |
855 | scsi_host_put(host); | 1134 | scsi_host_put(host); |
856 | 1135 | ||
1136 | free_pci_regions: | ||
1137 | pci_release_regions(pcidev); | ||
1138 | |||
857 | disable_pci_device: | 1139 | disable_pci_device: |
858 | pci_disable_device(pcidev); | 1140 | pci_disable_device(pcidev); |
859 | 1141 | ||
@@ -865,8 +1147,6 @@ static void hptiop_shutdown(struct pci_dev *pcidev) | |||
865 | { | 1147 | { |
866 | struct Scsi_Host *host = pci_get_drvdata(pcidev); | 1148 | struct Scsi_Host *host = pci_get_drvdata(pcidev); |
867 | struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata; | 1149 | struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata; |
868 | struct hpt_iopmu __iomem *iop = hba->iop; | ||
869 | u32 int_mask; | ||
870 | 1150 | ||
871 | dprintk("hptiop_shutdown(%p)\n", hba); | 1151 | dprintk("hptiop_shutdown(%p)\n", hba); |
872 | 1152 | ||
@@ -876,11 +1156,24 @@ static void hptiop_shutdown(struct pci_dev *pcidev) | |||
876 | hba->host->host_no); | 1156 | hba->host->host_no); |
877 | 1157 | ||
878 | /* disable all outbound interrupts */ | 1158 | /* disable all outbound interrupts */ |
879 | int_mask = readl(&iop->outbound_intmask); | 1159 | hba->ops->disable_intr(hba); |
1160 | } | ||
1161 | |||
1162 | static void hptiop_disable_intr_itl(struct hptiop_hba *hba) | ||
1163 | { | ||
1164 | u32 int_mask; | ||
1165 | |||
1166 | int_mask = readl(&hba->u.itl.iop->outbound_intmask); | ||
880 | writel(int_mask | | 1167 | writel(int_mask | |
881 | IOPMU_OUTBOUND_INT_MSG0 | IOPMU_OUTBOUND_INT_POSTQUEUE, | 1168 | IOPMU_OUTBOUND_INT_MSG0 | IOPMU_OUTBOUND_INT_POSTQUEUE, |
882 | &iop->outbound_intmask); | 1169 | &hba->u.itl.iop->outbound_intmask); |
883 | hptiop_pci_posting_flush(iop); | 1170 | readl(&hba->u.itl.iop->outbound_intmask); |
1171 | } | ||
1172 | |||
1173 | static void hptiop_disable_intr_mv(struct hptiop_hba *hba) | ||
1174 | { | ||
1175 | writel(0, &hba->u.mv.regs->outbound_intmask); | ||
1176 | readl(&hba->u.mv.regs->outbound_intmask); | ||
884 | } | 1177 | } |
885 | 1178 | ||
886 | static void hptiop_remove(struct pci_dev *pcidev) | 1179 | static void hptiop_remove(struct pci_dev *pcidev) |
@@ -901,7 +1194,10 @@ static void hptiop_remove(struct pci_dev *pcidev) | |||
901 | hba->dma_coherent, | 1194 | hba->dma_coherent, |
902 | hba->dma_coherent_handle); | 1195 | hba->dma_coherent_handle); |
903 | 1196 | ||
904 | iounmap(hba->iop); | 1197 | if (hba->ops->internal_memfree) |
1198 | hba->ops->internal_memfree(hba); | ||
1199 | |||
1200 | hba->ops->unmap_pci_bar(hba); | ||
905 | 1201 | ||
906 | pci_release_regions(hba->pcidev); | 1202 | pci_release_regions(hba->pcidev); |
907 | pci_set_drvdata(hba->pcidev, NULL); | 1203 | pci_set_drvdata(hba->pcidev, NULL); |
@@ -910,11 +1206,50 @@ static void hptiop_remove(struct pci_dev *pcidev) | |||
910 | scsi_host_put(host); | 1206 | scsi_host_put(host); |
911 | } | 1207 | } |
912 | 1208 | ||
1209 | static struct hptiop_adapter_ops hptiop_itl_ops = { | ||
1210 | .iop_wait_ready = iop_wait_ready_itl, | ||
1211 | .internal_memalloc = 0, | ||
1212 | .internal_memfree = 0, | ||
1213 | .map_pci_bar = hptiop_map_pci_bar_itl, | ||
1214 | .unmap_pci_bar = hptiop_unmap_pci_bar_itl, | ||
1215 | .enable_intr = hptiop_enable_intr_itl, | ||
1216 | .disable_intr = hptiop_disable_intr_itl, | ||
1217 | .get_config = iop_get_config_itl, | ||
1218 | .set_config = iop_set_config_itl, | ||
1219 | .iop_intr = iop_intr_itl, | ||
1220 | .post_msg = hptiop_post_msg_itl, | ||
1221 | .post_req = hptiop_post_req_itl, | ||
1222 | }; | ||
1223 | |||
1224 | static struct hptiop_adapter_ops hptiop_mv_ops = { | ||
1225 | .iop_wait_ready = iop_wait_ready_mv, | ||
1226 | .internal_memalloc = hptiop_internal_memalloc_mv, | ||
1227 | .internal_memfree = hptiop_internal_memfree_mv, | ||
1228 | .map_pci_bar = hptiop_map_pci_bar_mv, | ||
1229 | .unmap_pci_bar = hptiop_unmap_pci_bar_mv, | ||
1230 | .enable_intr = hptiop_enable_intr_mv, | ||
1231 | .disable_intr = hptiop_disable_intr_mv, | ||
1232 | .get_config = iop_get_config_mv, | ||
1233 | .set_config = iop_set_config_mv, | ||
1234 | .iop_intr = iop_intr_mv, | ||
1235 | .post_msg = hptiop_post_msg_mv, | ||
1236 | .post_req = hptiop_post_req_mv, | ||
1237 | }; | ||
1238 | |||
913 | static struct pci_device_id hptiop_id_table[] = { | 1239 | static struct pci_device_id hptiop_id_table[] = { |
914 | { PCI_VDEVICE(TTI, 0x3220) }, | 1240 | { PCI_VDEVICE(TTI, 0x3220), (kernel_ulong_t)&hptiop_itl_ops }, |
915 | { PCI_VDEVICE(TTI, 0x3320) }, | 1241 | { PCI_VDEVICE(TTI, 0x3320), (kernel_ulong_t)&hptiop_itl_ops }, |
916 | { PCI_VDEVICE(TTI, 0x3520) }, | 1242 | { PCI_VDEVICE(TTI, 0x3520), (kernel_ulong_t)&hptiop_itl_ops }, |
917 | { PCI_VDEVICE(TTI, 0x4320) }, | 1243 | { PCI_VDEVICE(TTI, 0x4320), (kernel_ulong_t)&hptiop_itl_ops }, |
1244 | { PCI_VDEVICE(TTI, 0x3510), (kernel_ulong_t)&hptiop_itl_ops }, | ||
1245 | { PCI_VDEVICE(TTI, 0x3511), (kernel_ulong_t)&hptiop_itl_ops }, | ||
1246 | { PCI_VDEVICE(TTI, 0x3521), (kernel_ulong_t)&hptiop_itl_ops }, | ||
1247 | { PCI_VDEVICE(TTI, 0x3522), (kernel_ulong_t)&hptiop_itl_ops }, | ||
1248 | { PCI_VDEVICE(TTI, 0x3410), (kernel_ulong_t)&hptiop_itl_ops }, | ||
1249 | { PCI_VDEVICE(TTI, 0x3540), (kernel_ulong_t)&hptiop_itl_ops }, | ||
1250 | { PCI_VDEVICE(TTI, 0x3120), (kernel_ulong_t)&hptiop_mv_ops }, | ||
1251 | { PCI_VDEVICE(TTI, 0x3122), (kernel_ulong_t)&hptiop_mv_ops }, | ||
1252 | { PCI_VDEVICE(TTI, 0x3020), (kernel_ulong_t)&hptiop_mv_ops }, | ||
918 | {}, | 1253 | {}, |
919 | }; | 1254 | }; |
920 | 1255 | ||