1700 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * HighPoint RR3xxx/4xxx controller driver for Linux4 * Copyright (C) 2006-2015 HighPoint Technologies, Inc. All Rights Reserved.5 *6 * Please report bugs/comments/suggestions to linux@highpoint-tech.com7 *8 * For more information, visit http://www.highpoint-tech.com9 */10#include <linux/module.h>11#include <linux/types.h>12#include <linux/string.h>13#include <linux/kernel.h>14#include <linux/pci.h>15#include <linux/interrupt.h>16#include <linux/errno.h>17#include <linux/delay.h>18#include <linux/timer.h>19#include <linux/spinlock.h>20#include <linux/gfp.h>21#include <linux/uaccess.h>22#include <asm/io.h>23#include <asm/div64.h>24#include <scsi/scsi_cmnd.h>25#include <scsi/scsi_device.h>26#include <scsi/scsi.h>27#include <scsi/scsi_tcq.h>28#include <scsi/scsi_host.h>29 30#include "hptiop.h"31 32MODULE_AUTHOR("HighPoint Technologies, Inc.");33MODULE_DESCRIPTION("HighPoint RocketRAID 3xxx/4xxx Controller Driver");34 35static char driver_name[] = "hptiop";36static const char driver_name_long[] = "RocketRAID 3xxx/4xxx Controller driver";37static const char driver_ver[] = "v1.10.0";38 39static int iop_send_sync_msg(struct hptiop_hba *hba, u32 msg, u32 millisec);40static void hptiop_finish_scsi_req(struct hptiop_hba *hba, u32 tag,41 struct hpt_iop_request_scsi_command *req);42static void hptiop_host_request_callback_itl(struct hptiop_hba *hba, u32 tag);43static void hptiop_iop_request_callback_itl(struct hptiop_hba *hba, u32 tag);44static void hptiop_message_callback(struct hptiop_hba *hba, u32 msg);45 46static int iop_wait_ready_itl(struct hptiop_hba *hba, u32 millisec)47{48 u32 req = 0;49 int i;50 51 for (i = 0; i < millisec; i++) {52 req = readl(&hba->u.itl.iop->inbound_queue);53 if (req != IOPMU_QUEUE_EMPTY)54 break;55 msleep(1);56 }57 58 if (req != IOPMU_QUEUE_EMPTY) {59 writel(req, &hba->u.itl.iop->outbound_queue);60 readl(&hba->u.itl.iop->outbound_intstatus);61 return 0;62 }63 64 return -1;65}66 67static int iop_wait_ready_mv(struct hptiop_hba *hba, u32 millisec)68{69 return iop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_NOP, millisec);70}71 72static int iop_wait_ready_mvfrey(struct hptiop_hba *hba, u32 millisec)73{74 return iop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_NOP, millisec);75}76 77static void hptiop_request_callback_itl(struct hptiop_hba *hba, u32 tag)78{79 if (tag & IOPMU_QUEUE_ADDR_HOST_BIT)80 hptiop_host_request_callback_itl(hba,81 tag & ~IOPMU_QUEUE_ADDR_HOST_BIT);82 else83 hptiop_iop_request_callback_itl(hba, tag);84}85 86static void hptiop_drain_outbound_queue_itl(struct hptiop_hba *hba)87{88 u32 req;89 90 while ((req = readl(&hba->u.itl.iop->outbound_queue)) !=91 IOPMU_QUEUE_EMPTY) {92 93 if (req & IOPMU_QUEUE_MASK_HOST_BITS)94 hptiop_request_callback_itl(hba, req);95 else {96 struct hpt_iop_request_header __iomem * p;97 98 p = (struct hpt_iop_request_header __iomem *)99 ((char __iomem *)hba->u.itl.iop + req);100 101 if (readl(&p->flags) & IOP_REQUEST_FLAG_SYNC_REQUEST) {102 if (readl(&p->context))103 hptiop_request_callback_itl(hba, req);104 else105 writel(1, &p->context);106 }107 else108 hptiop_request_callback_itl(hba, req);109 }110 }111}112 113static int iop_intr_itl(struct hptiop_hba *hba)114{115 struct hpt_iopmu_itl __iomem *iop = hba->u.itl.iop;116 void __iomem *plx = hba->u.itl.plx;117 u32 status;118 int ret = 0;119 120 if (plx && readl(plx + 0x11C5C) & 0xf)121 writel(1, plx + 0x11C60);122 123 status = readl(&iop->outbound_intstatus);124 125 if (status & IOPMU_OUTBOUND_INT_MSG0) {126 u32 msg = readl(&iop->outbound_msgaddr0);127 128 dprintk("received outbound msg %x\n", msg);129 writel(IOPMU_OUTBOUND_INT_MSG0, &iop->outbound_intstatus);130 hptiop_message_callback(hba, msg);131 ret = 1;132 }133 134 if (status & IOPMU_OUTBOUND_INT_POSTQUEUE) {135 hptiop_drain_outbound_queue_itl(hba);136 ret = 1;137 }138 139 return ret;140}141 142static u64 mv_outbound_read(struct hpt_iopmu_mv __iomem *mu)143{144 u32 outbound_tail = readl(&mu->outbound_tail);145 u32 outbound_head = readl(&mu->outbound_head);146 147 if (outbound_tail != outbound_head) {148 u64 p;149 150 memcpy_fromio(&p, &mu->outbound_q[mu->outbound_tail], 8);151 outbound_tail++;152 153 if (outbound_tail == MVIOP_QUEUE_LEN)154 outbound_tail = 0;155 writel(outbound_tail, &mu->outbound_tail);156 return p;157 } else158 return 0;159}160 161static void mv_inbound_write(u64 p, struct hptiop_hba *hba)162{163 u32 inbound_head = readl(&hba->u.mv.mu->inbound_head);164 u32 head = inbound_head + 1;165 166 if (head == MVIOP_QUEUE_LEN)167 head = 0;168 169 memcpy_toio(&hba->u.mv.mu->inbound_q[inbound_head], &p, 8);170 writel(head, &hba->u.mv.mu->inbound_head);171 writel(MVIOP_MU_INBOUND_INT_POSTQUEUE,172 &hba->u.mv.regs->inbound_doorbell);173}174 175static void hptiop_request_callback_mv(struct hptiop_hba *hba, u64 tag)176{177 u32 req_type = (tag >> 5) & 0x7;178 struct hpt_iop_request_scsi_command *req;179 180 dprintk("hptiop_request_callback_mv: tag=%llx\n", tag);181 182 BUG_ON((tag & MVIOP_MU_QUEUE_REQUEST_RETURN_CONTEXT) == 0);183 184 switch (req_type) {185 case IOP_REQUEST_TYPE_GET_CONFIG:186 case IOP_REQUEST_TYPE_SET_CONFIG:187 hba->msg_done = 1;188 break;189 190 case IOP_REQUEST_TYPE_SCSI_COMMAND:191 req = hba->reqs[tag >> 8].req_virt;192 if (likely(tag & MVIOP_MU_QUEUE_REQUEST_RESULT_BIT))193 req->header.result = cpu_to_le32(IOP_RESULT_SUCCESS);194 195 hptiop_finish_scsi_req(hba, tag>>8, req);196 break;197 198 default:199 break;200 }201}202 203static int iop_intr_mv(struct hptiop_hba *hba)204{205 u32 status;206 int ret = 0;207 208 status = readl(&hba->u.mv.regs->outbound_doorbell);209 writel(~status, &hba->u.mv.regs->outbound_doorbell);210 211 if (status & MVIOP_MU_OUTBOUND_INT_MSG) {212 u32 msg;213 msg = readl(&hba->u.mv.mu->outbound_msg);214 dprintk("received outbound msg %x\n", msg);215 hptiop_message_callback(hba, msg);216 ret = 1;217 }218 219 if (status & MVIOP_MU_OUTBOUND_INT_POSTQUEUE) {220 u64 tag;221 222 while ((tag = mv_outbound_read(hba->u.mv.mu)))223 hptiop_request_callback_mv(hba, tag);224 ret = 1;225 }226 227 return ret;228}229 230static void hptiop_request_callback_mvfrey(struct hptiop_hba *hba, u32 _tag)231{232 u32 req_type = _tag & 0xf;233 struct hpt_iop_request_scsi_command *req;234 235 switch (req_type) {236 case IOP_REQUEST_TYPE_GET_CONFIG:237 case IOP_REQUEST_TYPE_SET_CONFIG:238 hba->msg_done = 1;239 break;240 241 case IOP_REQUEST_TYPE_SCSI_COMMAND:242 req = hba->reqs[(_tag >> 4) & 0xff].req_virt;243 if (likely(_tag & IOPMU_QUEUE_REQUEST_RESULT_BIT))244 req->header.result = IOP_RESULT_SUCCESS;245 hptiop_finish_scsi_req(hba, (_tag >> 4) & 0xff, req);246 break;247 248 default:249 break;250 }251}252 253static int iop_intr_mvfrey(struct hptiop_hba *hba)254{255 u32 _tag, status, cptr, cur_rptr;256 int ret = 0;257 258 if (hba->initialized)259 writel(0, &(hba->u.mvfrey.mu->pcie_f0_int_enable));260 261 status = readl(&(hba->u.mvfrey.mu->f0_doorbell));262 if (status) {263 writel(status, &(hba->u.mvfrey.mu->f0_doorbell));264 if (status & CPU_TO_F0_DRBL_MSG_BIT) {265 u32 msg = readl(&(hba->u.mvfrey.mu->cpu_to_f0_msg_a));266 dprintk("received outbound msg %x\n", msg);267 hptiop_message_callback(hba, msg);268 }269 ret = 1;270 }271 272 status = readl(&(hba->u.mvfrey.mu->isr_cause));273 if (status) {274 writel(status, &(hba->u.mvfrey.mu->isr_cause));275 do {276 cptr = *hba->u.mvfrey.outlist_cptr & 0xff;277 cur_rptr = hba->u.mvfrey.outlist_rptr;278 while (cur_rptr != cptr) {279 cur_rptr++;280 if (cur_rptr == hba->u.mvfrey.list_count)281 cur_rptr = 0;282 283 _tag = hba->u.mvfrey.outlist[cur_rptr].val;284 BUG_ON(!(_tag & IOPMU_QUEUE_MASK_HOST_BITS));285 hptiop_request_callback_mvfrey(hba, _tag);286 ret = 1;287 }288 hba->u.mvfrey.outlist_rptr = cur_rptr;289 } while (cptr != (*hba->u.mvfrey.outlist_cptr & 0xff));290 }291 292 if (hba->initialized)293 writel(0x1010, &(hba->u.mvfrey.mu->pcie_f0_int_enable));294 295 return ret;296}297 298static int iop_send_sync_request_itl(struct hptiop_hba *hba,299 void __iomem *_req, u32 millisec)300{301 struct hpt_iop_request_header __iomem *req = _req;302 u32 i;303 304 writel(readl(&req->flags) | IOP_REQUEST_FLAG_SYNC_REQUEST, &req->flags);305 writel(0, &req->context);306 writel((unsigned long)req - (unsigned long)hba->u.itl.iop,307 &hba->u.itl.iop->inbound_queue);308 readl(&hba->u.itl.iop->outbound_intstatus);309 310 for (i = 0; i < millisec; i++) {311 iop_intr_itl(hba);312 if (readl(&req->context))313 return 0;314 msleep(1);315 }316 317 return -1;318}319 320static int iop_send_sync_request_mv(struct hptiop_hba *hba,321 u32 size_bits, u32 millisec)322{323 struct hpt_iop_request_header *reqhdr = hba->u.mv.internal_req;324 u32 i;325 326 hba->msg_done = 0;327 reqhdr->flags |= cpu_to_le32(IOP_REQUEST_FLAG_SYNC_REQUEST);328 mv_inbound_write(hba->u.mv.internal_req_phy |329 MVIOP_MU_QUEUE_ADDR_HOST_BIT | size_bits, hba);330 331 for (i = 0; i < millisec; i++) {332 iop_intr_mv(hba);333 if (hba->msg_done)334 return 0;335 msleep(1);336 }337 return -1;338}339 340static int iop_send_sync_request_mvfrey(struct hptiop_hba *hba,341 u32 size_bits, u32 millisec)342{343 struct hpt_iop_request_header *reqhdr =344 hba->u.mvfrey.internal_req.req_virt;345 u32 i;346 347 hba->msg_done = 0;348 reqhdr->flags |= cpu_to_le32(IOP_REQUEST_FLAG_SYNC_REQUEST);349 hba->ops->post_req(hba, &(hba->u.mvfrey.internal_req));350 351 for (i = 0; i < millisec; i++) {352 iop_intr_mvfrey(hba);353 if (hba->msg_done)354 break;355 msleep(1);356 }357 return hba->msg_done ? 0 : -1;358}359 360static void hptiop_post_msg_itl(struct hptiop_hba *hba, u32 msg)361{362 writel(msg, &hba->u.itl.iop->inbound_msgaddr0);363 readl(&hba->u.itl.iop->outbound_intstatus);364}365 366static void hptiop_post_msg_mv(struct hptiop_hba *hba, u32 msg)367{368 writel(msg, &hba->u.mv.mu->inbound_msg);369 writel(MVIOP_MU_INBOUND_INT_MSG, &hba->u.mv.regs->inbound_doorbell);370 readl(&hba->u.mv.regs->inbound_doorbell);371}372 373static void hptiop_post_msg_mvfrey(struct hptiop_hba *hba, u32 msg)374{375 writel(msg, &(hba->u.mvfrey.mu->f0_to_cpu_msg_a));376 readl(&(hba->u.mvfrey.mu->f0_to_cpu_msg_a));377}378 379static int iop_send_sync_msg(struct hptiop_hba *hba, u32 msg, u32 millisec)380{381 u32 i;382 383 hba->msg_done = 0;384 hba->ops->disable_intr(hba);385 hba->ops->post_msg(hba, msg);386 387 for (i = 0; i < millisec; i++) {388 spin_lock_irq(hba->host->host_lock);389 hba->ops->iop_intr(hba);390 spin_unlock_irq(hba->host->host_lock);391 if (hba->msg_done)392 break;393 msleep(1);394 }395 396 hba->ops->enable_intr(hba);397 return hba->msg_done? 0 : -1;398}399 400static int iop_get_config_itl(struct hptiop_hba *hba,401 struct hpt_iop_request_get_config *config)402{403 u32 req32;404 struct hpt_iop_request_get_config __iomem *req;405 406 req32 = readl(&hba->u.itl.iop->inbound_queue);407 if (req32 == IOPMU_QUEUE_EMPTY)408 return -1;409 410 req = (struct hpt_iop_request_get_config __iomem *)411 ((unsigned long)hba->u.itl.iop + req32);412 413 writel(0, &req->header.flags);414 writel(IOP_REQUEST_TYPE_GET_CONFIG, &req->header.type);415 writel(sizeof(struct hpt_iop_request_get_config), &req->header.size);416 writel(IOP_RESULT_PENDING, &req->header.result);417 418 if (iop_send_sync_request_itl(hba, req, 20000)) {419 dprintk("Get config send cmd failed\n");420 return -1;421 }422 423 memcpy_fromio(config, req, sizeof(*config));424 writel(req32, &hba->u.itl.iop->outbound_queue);425 return 0;426}427 428static int iop_get_config_mv(struct hptiop_hba *hba,429 struct hpt_iop_request_get_config *config)430{431 struct hpt_iop_request_get_config *req = hba->u.mv.internal_req;432 433 req->header.flags = cpu_to_le32(IOP_REQUEST_FLAG_OUTPUT_CONTEXT);434 req->header.type = cpu_to_le32(IOP_REQUEST_TYPE_GET_CONFIG);435 req->header.size =436 cpu_to_le32(sizeof(struct hpt_iop_request_get_config));437 req->header.result = cpu_to_le32(IOP_RESULT_PENDING);438 req->header.context = cpu_to_le32(IOP_REQUEST_TYPE_GET_CONFIG<<5);439 req->header.context_hi32 = 0;440 441 if (iop_send_sync_request_mv(hba, 0, 20000)) {442 dprintk("Get config send cmd failed\n");443 return -1;444 }445 446 memcpy(config, req, sizeof(struct hpt_iop_request_get_config));447 return 0;448}449 450static int iop_get_config_mvfrey(struct hptiop_hba *hba,451 struct hpt_iop_request_get_config *config)452{453 struct hpt_iop_request_get_config *info = hba->u.mvfrey.config;454 455 if (info->header.size != sizeof(struct hpt_iop_request_get_config) ||456 info->header.type != IOP_REQUEST_TYPE_GET_CONFIG)457 return -1;458 459 config->interface_version = info->interface_version;460 config->firmware_version = info->firmware_version;461 config->max_requests = info->max_requests;462 config->request_size = info->request_size;463 config->max_sg_count = info->max_sg_count;464 config->data_transfer_length = info->data_transfer_length;465 config->alignment_mask = info->alignment_mask;466 config->max_devices = info->max_devices;467 config->sdram_size = info->sdram_size;468 469 return 0;470}471 472static int iop_set_config_itl(struct hptiop_hba *hba,473 struct hpt_iop_request_set_config *config)474{475 u32 req32;476 struct hpt_iop_request_set_config __iomem *req;477 478 req32 = readl(&hba->u.itl.iop->inbound_queue);479 if (req32 == IOPMU_QUEUE_EMPTY)480 return -1;481 482 req = (struct hpt_iop_request_set_config __iomem *)483 ((unsigned long)hba->u.itl.iop + req32);484 485 memcpy_toio((u8 __iomem *)req + sizeof(struct hpt_iop_request_header),486 (u8 *)config + sizeof(struct hpt_iop_request_header),487 sizeof(struct hpt_iop_request_set_config) -488 sizeof(struct hpt_iop_request_header));489 490 writel(0, &req->header.flags);491 writel(IOP_REQUEST_TYPE_SET_CONFIG, &req->header.type);492 writel(sizeof(struct hpt_iop_request_set_config), &req->header.size);493 writel(IOP_RESULT_PENDING, &req->header.result);494 495 if (iop_send_sync_request_itl(hba, req, 20000)) {496 dprintk("Set config send cmd failed\n");497 return -1;498 }499 500 writel(req32, &hba->u.itl.iop->outbound_queue);501 return 0;502}503 504static int iop_set_config_mv(struct hptiop_hba *hba,505 struct hpt_iop_request_set_config *config)506{507 struct hpt_iop_request_set_config *req = hba->u.mv.internal_req;508 509 memcpy(req, config, sizeof(struct hpt_iop_request_set_config));510 req->header.flags = cpu_to_le32(IOP_REQUEST_FLAG_OUTPUT_CONTEXT);511 req->header.type = cpu_to_le32(IOP_REQUEST_TYPE_SET_CONFIG);512 req->header.size =513 cpu_to_le32(sizeof(struct hpt_iop_request_set_config));514 req->header.result = cpu_to_le32(IOP_RESULT_PENDING);515 req->header.context = cpu_to_le32(IOP_REQUEST_TYPE_SET_CONFIG<<5);516 req->header.context_hi32 = 0;517 518 if (iop_send_sync_request_mv(hba, 0, 20000)) {519 dprintk("Set config send cmd failed\n");520 return -1;521 }522 523 return 0;524}525 526static int iop_set_config_mvfrey(struct hptiop_hba *hba,527 struct hpt_iop_request_set_config *config)528{529 struct hpt_iop_request_set_config *req =530 hba->u.mvfrey.internal_req.req_virt;531 532 memcpy(req, config, sizeof(struct hpt_iop_request_set_config));533 req->header.flags = cpu_to_le32(IOP_REQUEST_FLAG_OUTPUT_CONTEXT);534 req->header.type = cpu_to_le32(IOP_REQUEST_TYPE_SET_CONFIG);535 req->header.size =536 cpu_to_le32(sizeof(struct hpt_iop_request_set_config));537 req->header.result = cpu_to_le32(IOP_RESULT_PENDING);538 req->header.context = cpu_to_le32(IOP_REQUEST_TYPE_SET_CONFIG<<5);539 req->header.context_hi32 = 0;540 541 if (iop_send_sync_request_mvfrey(hba, 0, 20000)) {542 dprintk("Set config send cmd failed\n");543 return -1;544 }545 546 return 0;547}548 549static void hptiop_enable_intr_itl(struct hptiop_hba *hba)550{551 writel(~(IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0),552 &hba->u.itl.iop->outbound_intmask);553}554 555static void hptiop_enable_intr_mv(struct hptiop_hba *hba)556{557 writel(MVIOP_MU_OUTBOUND_INT_POSTQUEUE | MVIOP_MU_OUTBOUND_INT_MSG,558 &hba->u.mv.regs->outbound_intmask);559}560 561static void hptiop_enable_intr_mvfrey(struct hptiop_hba *hba)562{563 writel(CPU_TO_F0_DRBL_MSG_BIT, &(hba->u.mvfrey.mu->f0_doorbell_enable));564 writel(0x1, &(hba->u.mvfrey.mu->isr_enable));565 writel(0x1010, &(hba->u.mvfrey.mu->pcie_f0_int_enable));566}567 568static int hptiop_initialize_iop(struct hptiop_hba *hba)569{570 /* enable interrupts */571 hba->ops->enable_intr(hba);572 573 hba->initialized = 1;574 575 /* start background tasks */576 if (iop_send_sync_msg(hba,577 IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 5000)) {578 printk(KERN_ERR "scsi%d: fail to start background task\n",579 hba->host->host_no);580 return -1;581 }582 return 0;583}584 585static void __iomem *hptiop_map_pci_bar(struct hptiop_hba *hba, int index)586{587 u32 mem_base_phy, length;588 void __iomem *mem_base_virt;589 590 struct pci_dev *pcidev = hba->pcidev;591 592 593 if (!(pci_resource_flags(pcidev, index) & IORESOURCE_MEM)) {594 printk(KERN_ERR "scsi%d: pci resource invalid\n",595 hba->host->host_no);596 return NULL;597 }598 599 mem_base_phy = pci_resource_start(pcidev, index);600 length = pci_resource_len(pcidev, index);601 mem_base_virt = ioremap(mem_base_phy, length);602 603 if (!mem_base_virt) {604 printk(KERN_ERR "scsi%d: Fail to ioremap memory space\n",605 hba->host->host_no);606 return NULL;607 }608 return mem_base_virt;609}610 611static int hptiop_map_pci_bar_itl(struct hptiop_hba *hba)612{613 struct pci_dev *pcidev = hba->pcidev;614 hba->u.itl.iop = hptiop_map_pci_bar(hba, 0);615 if (hba->u.itl.iop == NULL)616 return -1;617 if ((pcidev->device & 0xff00) == 0x4400) {618 hba->u.itl.plx = hba->u.itl.iop;619 hba->u.itl.iop = hptiop_map_pci_bar(hba, 2);620 if (hba->u.itl.iop == NULL) {621 iounmap(hba->u.itl.plx);622 return -1;623 }624 }625 return 0;626}627 628static void hptiop_unmap_pci_bar_itl(struct hptiop_hba *hba)629{630 if (hba->u.itl.plx)631 iounmap(hba->u.itl.plx);632 iounmap(hba->u.itl.iop);633}634 635static int hptiop_map_pci_bar_mv(struct hptiop_hba *hba)636{637 hba->u.mv.regs = hptiop_map_pci_bar(hba, 0);638 if (hba->u.mv.regs == NULL)639 return -1;640 641 hba->u.mv.mu = hptiop_map_pci_bar(hba, 2);642 if (hba->u.mv.mu == NULL) {643 iounmap(hba->u.mv.regs);644 return -1;645 }646 647 return 0;648}649 650static int hptiop_map_pci_bar_mvfrey(struct hptiop_hba *hba)651{652 hba->u.mvfrey.config = hptiop_map_pci_bar(hba, 0);653 if (hba->u.mvfrey.config == NULL)654 return -1;655 656 hba->u.mvfrey.mu = hptiop_map_pci_bar(hba, 2);657 if (hba->u.mvfrey.mu == NULL) {658 iounmap(hba->u.mvfrey.config);659 return -1;660 }661 662 return 0;663}664 665static void hptiop_unmap_pci_bar_mv(struct hptiop_hba *hba)666{667 iounmap(hba->u.mv.regs);668 iounmap(hba->u.mv.mu);669}670 671static void hptiop_unmap_pci_bar_mvfrey(struct hptiop_hba *hba)672{673 iounmap(hba->u.mvfrey.config);674 iounmap(hba->u.mvfrey.mu);675}676 677static void hptiop_message_callback(struct hptiop_hba *hba, u32 msg)678{679 dprintk("iop message 0x%x\n", msg);680 681 if (msg == IOPMU_INBOUND_MSG0_NOP ||682 msg == IOPMU_INBOUND_MSG0_RESET_COMM)683 hba->msg_done = 1;684 685 if (!hba->initialized)686 return;687 688 if (msg == IOPMU_INBOUND_MSG0_RESET) {689 atomic_set(&hba->resetting, 0);690 wake_up(&hba->reset_wq);691 }692 else if (msg <= IOPMU_INBOUND_MSG0_MAX)693 hba->msg_done = 1;694}695 696static struct hptiop_request *get_req(struct hptiop_hba *hba)697{698 struct hptiop_request *ret;699 700 dprintk("get_req : req=%p\n", hba->req_list);701 702 ret = hba->req_list;703 if (ret)704 hba->req_list = ret->next;705 706 return ret;707}708 709static void free_req(struct hptiop_hba *hba, struct hptiop_request *req)710{711 dprintk("free_req(%d, %p)\n", req->index, req);712 req->next = hba->req_list;713 hba->req_list = req;714}715 716static void hptiop_finish_scsi_req(struct hptiop_hba *hba, u32 tag,717 struct hpt_iop_request_scsi_command *req)718{719 struct scsi_cmnd *scp;720 721 dprintk("hptiop_finish_scsi_req: req=%p, type=%d, "722 "result=%d, context=0x%x tag=%d\n",723 req, req->header.type, req->header.result,724 req->header.context, tag);725 726 BUG_ON(!req->header.result);727 BUG_ON(req->header.type != cpu_to_le32(IOP_REQUEST_TYPE_SCSI_COMMAND));728 729 scp = hba->reqs[tag].scp;730 731 if (HPT_SCP(scp)->mapped)732 scsi_dma_unmap(scp);733 734 switch (le32_to_cpu(req->header.result)) {735 case IOP_RESULT_SUCCESS:736 scsi_set_resid(scp,737 scsi_bufflen(scp) - le32_to_cpu(req->dataxfer_length));738 scp->result = (DID_OK<<16);739 break;740 case IOP_RESULT_BAD_TARGET:741 scp->result = (DID_BAD_TARGET<<16);742 break;743 case IOP_RESULT_BUSY:744 scp->result = (DID_BUS_BUSY<<16);745 break;746 case IOP_RESULT_RESET:747 scp->result = (DID_RESET<<16);748 break;749 case IOP_RESULT_FAIL:750 scp->result = (DID_ERROR<<16);751 break;752 case IOP_RESULT_INVALID_REQUEST:753 scp->result = (DID_ABORT<<16);754 break;755 case IOP_RESULT_CHECK_CONDITION:756 scsi_set_resid(scp,757 scsi_bufflen(scp) - le32_to_cpu(req->dataxfer_length));758 scp->result = SAM_STAT_CHECK_CONDITION;759 memcpy(scp->sense_buffer, &req->sg_list, SCSI_SENSE_BUFFERSIZE);760 goto skip_resid;761 762 default:763 scp->result = DID_ABORT << 16;764 break;765 }766 767 scsi_set_resid(scp,768 scsi_bufflen(scp) - le32_to_cpu(req->dataxfer_length));769 770skip_resid:771 dprintk("scsi_done(%p)\n", scp);772 scsi_done(scp);773 free_req(hba, &hba->reqs[tag]);774}775 776static void hptiop_host_request_callback_itl(struct hptiop_hba *hba, u32 _tag)777{778 struct hpt_iop_request_scsi_command *req;779 u32 tag;780 781 if (hba->iopintf_v2) {782 tag = _tag & ~IOPMU_QUEUE_REQUEST_RESULT_BIT;783 req = hba->reqs[tag].req_virt;784 if (likely(_tag & IOPMU_QUEUE_REQUEST_RESULT_BIT))785 req->header.result = cpu_to_le32(IOP_RESULT_SUCCESS);786 } else {787 tag = _tag;788 req = hba->reqs[tag].req_virt;789 }790 791 hptiop_finish_scsi_req(hba, tag, req);792}793 794static void hptiop_iop_request_callback_itl(struct hptiop_hba *hba, u32 tag)795{796 struct hpt_iop_request_header __iomem *req;797 struct hpt_iop_request_ioctl_command __iomem *p;798 struct hpt_ioctl_k *arg;799 800 req = (struct hpt_iop_request_header __iomem *)801 ((unsigned long)hba->u.itl.iop + tag);802 dprintk("hptiop_iop_request_callback_itl: req=%p, type=%d, "803 "result=%d, context=0x%x tag=%d\n",804 req, readl(&req->type), readl(&req->result),805 readl(&req->context), tag);806 807 BUG_ON(!readl(&req->result));808 BUG_ON(readl(&req->type) != IOP_REQUEST_TYPE_IOCTL_COMMAND);809 810 p = (struct hpt_iop_request_ioctl_command __iomem *)req;811 arg = (struct hpt_ioctl_k *)(unsigned long)812 (readl(&req->context) |813 ((u64)readl(&req->context_hi32)<<32));814 815 if (readl(&req->result) == IOP_RESULT_SUCCESS) {816 arg->result = HPT_IOCTL_RESULT_OK;817 818 if (arg->outbuf_size)819 memcpy_fromio(arg->outbuf,820 &p->buf[(readl(&p->inbuf_size) + 3)& ~3],821 arg->outbuf_size);822 823 if (arg->bytes_returned)824 *arg->bytes_returned = arg->outbuf_size;825 }826 else827 arg->result = HPT_IOCTL_RESULT_FAILED;828 829 arg->done(arg);830 writel(tag, &hba->u.itl.iop->outbound_queue);831}832 833static irqreturn_t hptiop_intr(int irq, void *dev_id)834{835 struct hptiop_hba *hba = dev_id;836 int handled;837 unsigned long flags;838 839 spin_lock_irqsave(hba->host->host_lock, flags);840 handled = hba->ops->iop_intr(hba);841 spin_unlock_irqrestore(hba->host->host_lock, flags);842 843 return handled;844}845 846static int hptiop_buildsgl(struct scsi_cmnd *scp, struct hpt_iopsg *psg)847{848 struct Scsi_Host *host = scp->device->host;849 struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata;850 struct scatterlist *sg;851 int idx, nseg;852 853 nseg = scsi_dma_map(scp);854 BUG_ON(nseg < 0);855 if (!nseg)856 return 0;857 858 HPT_SCP(scp)->sgcnt = nseg;859 HPT_SCP(scp)->mapped = 1;860 861 BUG_ON(HPT_SCP(scp)->sgcnt > hba->max_sg_descriptors);862 863 scsi_for_each_sg(scp, sg, HPT_SCP(scp)->sgcnt, idx) {864 psg[idx].pci_address = cpu_to_le64(sg_dma_address(sg)) |865 hba->ops->host_phy_flag;866 psg[idx].size = cpu_to_le32(sg_dma_len(sg));867 psg[idx].eot = (idx == HPT_SCP(scp)->sgcnt - 1) ?868 cpu_to_le32(1) : 0;869 }870 return HPT_SCP(scp)->sgcnt;871}872 873static void hptiop_post_req_itl(struct hptiop_hba *hba,874 struct hptiop_request *_req)875{876 struct hpt_iop_request_header *reqhdr = _req->req_virt;877 878 reqhdr->context = cpu_to_le32(IOPMU_QUEUE_ADDR_HOST_BIT |879 (u32)_req->index);880 reqhdr->context_hi32 = 0;881 882 if (hba->iopintf_v2) {883 u32 size, size_bits;884 885 size = le32_to_cpu(reqhdr->size);886 if (size < 256)887 size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT;888 else if (size < 512)889 size_bits = IOPMU_QUEUE_ADDR_HOST_BIT;890 else891 size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT |892 IOPMU_QUEUE_ADDR_HOST_BIT;893 writel(_req->req_shifted_phy | size_bits,894 &hba->u.itl.iop->inbound_queue);895 } else896 writel(_req->req_shifted_phy | IOPMU_QUEUE_ADDR_HOST_BIT,897 &hba->u.itl.iop->inbound_queue);898}899 900static void hptiop_post_req_mv(struct hptiop_hba *hba,901 struct hptiop_request *_req)902{903 struct hpt_iop_request_header *reqhdr = _req->req_virt;904 u32 size, size_bit;905 906 reqhdr->context = cpu_to_le32(_req->index<<8 |907 IOP_REQUEST_TYPE_SCSI_COMMAND<<5);908 reqhdr->context_hi32 = 0;909 size = le32_to_cpu(reqhdr->size);910 911 if (size <= 256)912 size_bit = 0;913 else if (size <= 256*2)914 size_bit = 1;915 else if (size <= 256*3)916 size_bit = 2;917 else918 size_bit = 3;919 920 mv_inbound_write((_req->req_shifted_phy << 5) |921 MVIOP_MU_QUEUE_ADDR_HOST_BIT | size_bit, hba);922}923 924static void hptiop_post_req_mvfrey(struct hptiop_hba *hba,925 struct hptiop_request *_req)926{927 struct hpt_iop_request_header *reqhdr = _req->req_virt;928 u32 index;929 930 reqhdr->flags |= cpu_to_le32(IOP_REQUEST_FLAG_OUTPUT_CONTEXT |931 IOP_REQUEST_FLAG_ADDR_BITS |932 ((_req->req_shifted_phy >> 11) & 0xffff0000));933 reqhdr->context = cpu_to_le32(IOPMU_QUEUE_ADDR_HOST_BIT |934 (_req->index << 4) | reqhdr->type);935 reqhdr->context_hi32 = cpu_to_le32((_req->req_shifted_phy << 5) &936 0xffffffff);937 938 hba->u.mvfrey.inlist_wptr++;939 index = hba->u.mvfrey.inlist_wptr & 0x3fff;940 941 if (index == hba->u.mvfrey.list_count) {942 index = 0;943 hba->u.mvfrey.inlist_wptr &= ~0x3fff;944 hba->u.mvfrey.inlist_wptr ^= CL_POINTER_TOGGLE;945 }946 947 hba->u.mvfrey.inlist[index].addr =948 (dma_addr_t)_req->req_shifted_phy << 5;949 hba->u.mvfrey.inlist[index].intrfc_len = (reqhdr->size + 3) / 4;950 writel(hba->u.mvfrey.inlist_wptr,951 &(hba->u.mvfrey.mu->inbound_write_ptr));952 readl(&(hba->u.mvfrey.mu->inbound_write_ptr));953}954 955static int hptiop_reset_comm_itl(struct hptiop_hba *hba)956{957 return 0;958}959 960static int hptiop_reset_comm_mv(struct hptiop_hba *hba)961{962 return 0;963}964 965static int hptiop_reset_comm_mvfrey(struct hptiop_hba *hba)966{967 u32 list_count = hba->u.mvfrey.list_count;968 969 if (iop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET_COMM, 3000))970 return -1;971 972 /* wait 100ms for MCU ready */973 msleep(100);974 975 writel(cpu_to_le32(hba->u.mvfrey.inlist_phy & 0xffffffff),976 &(hba->u.mvfrey.mu->inbound_base));977 writel(cpu_to_le32((hba->u.mvfrey.inlist_phy >> 16) >> 16),978 &(hba->u.mvfrey.mu->inbound_base_high));979 980 writel(cpu_to_le32(hba->u.mvfrey.outlist_phy & 0xffffffff),981 &(hba->u.mvfrey.mu->outbound_base));982 writel(cpu_to_le32((hba->u.mvfrey.outlist_phy >> 16) >> 16),983 &(hba->u.mvfrey.mu->outbound_base_high));984 985 writel(cpu_to_le32(hba->u.mvfrey.outlist_cptr_phy & 0xffffffff),986 &(hba->u.mvfrey.mu->outbound_shadow_base));987 writel(cpu_to_le32((hba->u.mvfrey.outlist_cptr_phy >> 16) >> 16),988 &(hba->u.mvfrey.mu->outbound_shadow_base_high));989 990 hba->u.mvfrey.inlist_wptr = (list_count - 1) | CL_POINTER_TOGGLE;991 *hba->u.mvfrey.outlist_cptr = (list_count - 1) | CL_POINTER_TOGGLE;992 hba->u.mvfrey.outlist_rptr = list_count - 1;993 return 0;994}995 996static int hptiop_queuecommand_lck(struct scsi_cmnd *scp)997{998 struct Scsi_Host *host = scp->device->host;999 struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata;1000 struct hpt_iop_request_scsi_command *req;1001 int sg_count = 0;1002 struct hptiop_request *_req;1003 1004 _req = get_req(hba);1005 if (_req == NULL) {1006 dprintk("hptiop_queuecmd : no free req\n");1007 return SCSI_MLQUEUE_HOST_BUSY;1008 }1009 1010 _req->scp = scp;1011 1012 dprintk("hptiop_queuecmd(scp=%p) %d/%d/%d/%llu cdb=(%08x-%08x-%08x-%08x) "1013 "req_index=%d, req=%p\n",1014 scp,1015 host->host_no, scp->device->channel,1016 scp->device->id, scp->device->lun,1017 cpu_to_be32(((u32 *)scp->cmnd)[0]),1018 cpu_to_be32(((u32 *)scp->cmnd)[1]),1019 cpu_to_be32(((u32 *)scp->cmnd)[2]),1020 cpu_to_be32(((u32 *)scp->cmnd)[3]),1021 _req->index, _req->req_virt);1022 1023 scp->result = 0;1024 1025 if (scp->device->channel ||1026 (scp->device->id > hba->max_devices) ||1027 ((scp->device->id == (hba->max_devices-1)) && scp->device->lun)) {1028 scp->result = DID_BAD_TARGET << 16;1029 free_req(hba, _req);1030 goto cmd_done;1031 }1032 1033 req = _req->req_virt;1034 1035 /* build S/G table */1036 sg_count = hptiop_buildsgl(scp, req->sg_list);1037 if (!sg_count)1038 HPT_SCP(scp)->mapped = 0;1039 1040 req->header.flags = cpu_to_le32(IOP_REQUEST_FLAG_OUTPUT_CONTEXT);1041 req->header.type = cpu_to_le32(IOP_REQUEST_TYPE_SCSI_COMMAND);1042 req->header.result = cpu_to_le32(IOP_RESULT_PENDING);1043 req->dataxfer_length = cpu_to_le32(scsi_bufflen(scp));1044 req->channel = scp->device->channel;1045 req->target = scp->device->id;1046 req->lun = scp->device->lun;1047 req->header.size = cpu_to_le32(struct_size(req, sg_list, sg_count));1048 1049 memcpy(req->cdb, scp->cmnd, sizeof(req->cdb));1050 hba->ops->post_req(hba, _req);1051 return 0;1052 1053cmd_done:1054 dprintk("scsi_done(scp=%p)\n", scp);1055 scsi_done(scp);1056 return 0;1057}1058 1059static DEF_SCSI_QCMD(hptiop_queuecommand)1060 1061static const char *hptiop_info(struct Scsi_Host *host)1062{1063 return driver_name_long;1064}1065 1066static int hptiop_reset_hba(struct hptiop_hba *hba)1067{1068 if (atomic_xchg(&hba->resetting, 1) == 0) {1069 atomic_inc(&hba->reset_count);1070 hba->ops->post_msg(hba, IOPMU_INBOUND_MSG0_RESET);1071 }1072 1073 wait_event_timeout(hba->reset_wq,1074 atomic_read(&hba->resetting) == 0, 60 * HZ);1075 1076 if (atomic_read(&hba->resetting)) {1077 /* IOP is in unknown state, abort reset */1078 printk(KERN_ERR "scsi%d: reset failed\n", hba->host->host_no);1079 return -1;1080 }1081 1082 if (iop_send_sync_msg(hba,1083 IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 5000)) {1084 dprintk("scsi%d: fail to start background task\n",1085 hba->host->host_no);1086 }1087 1088 return 0;1089}1090 1091static int hptiop_reset(struct scsi_cmnd *scp)1092{1093 struct hptiop_hba * hba = (struct hptiop_hba *)scp->device->host->hostdata;1094 1095 printk(KERN_WARNING "hptiop_reset(%d/%d/%d)\n",1096 scp->device->host->host_no, -1, -1);1097 1098 return hptiop_reset_hba(hba)? FAILED : SUCCESS;1099}1100 1101static int hptiop_adjust_disk_queue_depth(struct scsi_device *sdev,1102 int queue_depth)1103{1104 struct hptiop_hba *hba = (struct hptiop_hba *)sdev->host->hostdata;1105 1106 if (queue_depth > hba->max_requests)1107 queue_depth = hba->max_requests;1108 return scsi_change_queue_depth(sdev, queue_depth);1109}1110 1111static ssize_t hptiop_show_version(struct device *dev,1112 struct device_attribute *attr, char *buf)1113{1114 return snprintf(buf, PAGE_SIZE, "%s\n", driver_ver);1115}1116 1117static ssize_t hptiop_show_fw_version(struct device *dev,1118 struct device_attribute *attr, char *buf)1119{1120 struct Scsi_Host *host = class_to_shost(dev);1121 struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata;1122 1123 return snprintf(buf, PAGE_SIZE, "%d.%d.%d.%d\n",1124 hba->firmware_version >> 24,1125 (hba->firmware_version >> 16) & 0xff,1126 (hba->firmware_version >> 8) & 0xff,1127 hba->firmware_version & 0xff);1128}1129 1130static struct device_attribute hptiop_attr_version = {1131 .attr = {1132 .name = "driver-version",1133 .mode = S_IRUGO,1134 },1135 .show = hptiop_show_version,1136};1137 1138static struct device_attribute hptiop_attr_fw_version = {1139 .attr = {1140 .name = "firmware-version",1141 .mode = S_IRUGO,1142 },1143 .show = hptiop_show_fw_version,1144};1145 1146static struct attribute *hptiop_host_attrs[] = {1147 &hptiop_attr_version.attr,1148 &hptiop_attr_fw_version.attr,1149 NULL1150};1151 1152ATTRIBUTE_GROUPS(hptiop_host);1153 1154static int hptiop_device_configure(struct scsi_device *sdev,1155 struct queue_limits *lim)1156{1157 if (sdev->type == TYPE_TAPE)1158 lim->max_hw_sectors = 8192;1159 return 0;1160}1161 1162static const struct scsi_host_template driver_template = {1163 .module = THIS_MODULE,1164 .name = driver_name,1165 .queuecommand = hptiop_queuecommand,1166 .eh_host_reset_handler = hptiop_reset,1167 .info = hptiop_info,1168 .emulated = 0,1169 .proc_name = driver_name,1170 .shost_groups = hptiop_host_groups,1171 .device_configure = hptiop_device_configure,1172 .this_id = -1,1173 .change_queue_depth = hptiop_adjust_disk_queue_depth,1174 .cmd_size = sizeof(struct hpt_cmd_priv),1175};1176 1177static int hptiop_internal_memalloc_itl(struct hptiop_hba *hba)1178{1179 return 0;1180}1181 1182static int hptiop_internal_memalloc_mv(struct hptiop_hba *hba)1183{1184 hba->u.mv.internal_req = dma_alloc_coherent(&hba->pcidev->dev,1185 0x800, &hba->u.mv.internal_req_phy, GFP_KERNEL);1186 if (hba->u.mv.internal_req)1187 return 0;1188 else1189 return -1;1190}1191 1192static int hptiop_internal_memalloc_mvfrey(struct hptiop_hba *hba)1193{1194 u32 list_count = readl(&hba->u.mvfrey.mu->inbound_conf_ctl);1195 char *p;1196 dma_addr_t phy;1197 1198 BUG_ON(hba->max_request_size == 0);1199 1200 if (list_count == 0) {1201 BUG_ON(1);1202 return -1;1203 }1204 1205 list_count >>= 16;1206 1207 hba->u.mvfrey.list_count = list_count;1208 hba->u.mvfrey.internal_mem_size = 0x800 +1209 list_count * sizeof(struct mvfrey_inlist_entry) +1210 list_count * sizeof(struct mvfrey_outlist_entry) +1211 sizeof(int);1212 1213 p = dma_alloc_coherent(&hba->pcidev->dev,1214 hba->u.mvfrey.internal_mem_size, &phy, GFP_KERNEL);1215 if (!p)1216 return -1;1217 1218 hba->u.mvfrey.internal_req.req_virt = p;1219 hba->u.mvfrey.internal_req.req_shifted_phy = phy >> 5;1220 hba->u.mvfrey.internal_req.scp = NULL;1221 hba->u.mvfrey.internal_req.next = NULL;1222 1223 p += 0x800;1224 phy += 0x800;1225 1226 hba->u.mvfrey.inlist = (struct mvfrey_inlist_entry *)p;1227 hba->u.mvfrey.inlist_phy = phy;1228 1229 p += list_count * sizeof(struct mvfrey_inlist_entry);1230 phy += list_count * sizeof(struct mvfrey_inlist_entry);1231 1232 hba->u.mvfrey.outlist = (struct mvfrey_outlist_entry *)p;1233 hba->u.mvfrey.outlist_phy = phy;1234 1235 p += list_count * sizeof(struct mvfrey_outlist_entry);1236 phy += list_count * sizeof(struct mvfrey_outlist_entry);1237 1238 hba->u.mvfrey.outlist_cptr = (__le32 *)p;1239 hba->u.mvfrey.outlist_cptr_phy = phy;1240 1241 return 0;1242}1243 1244static int hptiop_internal_memfree_itl(struct hptiop_hba *hba)1245{1246 return 0;1247}1248 1249static int hptiop_internal_memfree_mv(struct hptiop_hba *hba)1250{1251 if (hba->u.mv.internal_req) {1252 dma_free_coherent(&hba->pcidev->dev, 0x800,1253 hba->u.mv.internal_req, hba->u.mv.internal_req_phy);1254 return 0;1255 } else1256 return -1;1257}1258 1259static int hptiop_internal_memfree_mvfrey(struct hptiop_hba *hba)1260{1261 if (hba->u.mvfrey.internal_req.req_virt) {1262 dma_free_coherent(&hba->pcidev->dev,1263 hba->u.mvfrey.internal_mem_size,1264 hba->u.mvfrey.internal_req.req_virt,1265 (dma_addr_t)1266 hba->u.mvfrey.internal_req.req_shifted_phy << 5);1267 return 0;1268 } else1269 return -1;1270}1271 1272static int hptiop_probe(struct pci_dev *pcidev, const struct pci_device_id *id)1273{1274 struct Scsi_Host *host = NULL;1275 struct hptiop_hba *hba;1276 struct hptiop_adapter_ops *iop_ops;1277 struct hpt_iop_request_get_config iop_config;1278 struct hpt_iop_request_set_config set_config;1279 dma_addr_t start_phy;1280 void *start_virt;1281 u32 offset, i, req_size;1282 int rc;1283 1284 dprintk("hptiop_probe(%p)\n", pcidev);1285 1286 if (pci_enable_device(pcidev)) {1287 printk(KERN_ERR "hptiop: fail to enable pci device\n");1288 return -ENODEV;1289 }1290 1291 printk(KERN_INFO "adapter at PCI %d:%d:%d, IRQ %d\n",1292 pcidev->bus->number, pcidev->devfn >> 3, pcidev->devfn & 7,1293 pcidev->irq);1294 1295 pci_set_master(pcidev);1296 1297 /* Enable 64bit DMA if possible */1298 iop_ops = (struct hptiop_adapter_ops *)id->driver_data;1299 rc = dma_set_mask(&pcidev->dev,1300 DMA_BIT_MASK(iop_ops->hw_dma_bit_mask));1301 if (rc)1302 rc = dma_set_mask(&pcidev->dev, DMA_BIT_MASK(32));1303 1304 if (rc) {1305 printk(KERN_ERR "hptiop: fail to set dma_mask\n");1306 goto disable_pci_device;1307 }1308 1309 if (pci_request_regions(pcidev, driver_name)) {1310 printk(KERN_ERR "hptiop: pci_request_regions failed\n");1311 goto disable_pci_device;1312 }1313 1314 host = scsi_host_alloc(&driver_template, sizeof(struct hptiop_hba));1315 if (!host) {1316 printk(KERN_ERR "hptiop: fail to alloc scsi host\n");1317 goto free_pci_regions;1318 }1319 1320 hba = (struct hptiop_hba *)host->hostdata;1321 memset(hba, 0, sizeof(struct hptiop_hba));1322 1323 hba->ops = iop_ops;1324 hba->pcidev = pcidev;1325 hba->host = host;1326 hba->initialized = 0;1327 hba->iopintf_v2 = 0;1328 1329 atomic_set(&hba->resetting, 0);1330 atomic_set(&hba->reset_count, 0);1331 1332 init_waitqueue_head(&hba->reset_wq);1333 init_waitqueue_head(&hba->ioctl_wq);1334 1335 host->max_lun = 128;1336 host->max_channel = 0;1337 host->io_port = 0;1338 host->n_io_port = 0;1339 host->irq = pcidev->irq;1340 1341 if (hba->ops->map_pci_bar(hba))1342 goto free_scsi_host;1343 1344 if (hba->ops->iop_wait_ready(hba, 20000)) {1345 printk(KERN_ERR "scsi%d: firmware not ready\n",1346 hba->host->host_no);1347 goto unmap_pci_bar;1348 }1349 1350 if (hba->ops->family == MV_BASED_IOP) {1351 if (hba->ops->internal_memalloc(hba)) {1352 printk(KERN_ERR "scsi%d: internal_memalloc failed\n",1353 hba->host->host_no);1354 goto unmap_pci_bar;1355 }1356 }1357 1358 if (hba->ops->get_config(hba, &iop_config)) {1359 printk(KERN_ERR "scsi%d: get config failed\n",1360 hba->host->host_no);1361 goto unmap_pci_bar;1362 }1363 1364 hba->max_requests = min(le32_to_cpu(iop_config.max_requests),1365 HPTIOP_MAX_REQUESTS);1366 hba->max_devices = le32_to_cpu(iop_config.max_devices);1367 hba->max_request_size = le32_to_cpu(iop_config.request_size);1368 hba->max_sg_descriptors = le32_to_cpu(iop_config.max_sg_count);1369 hba->firmware_version = le32_to_cpu(iop_config.firmware_version);1370 hba->interface_version = le32_to_cpu(iop_config.interface_version);1371 hba->sdram_size = le32_to_cpu(iop_config.sdram_size);1372 1373 if (hba->ops->family == MVFREY_BASED_IOP) {1374 if (hba->ops->internal_memalloc(hba)) {1375 printk(KERN_ERR "scsi%d: internal_memalloc failed\n",1376 hba->host->host_no);1377 goto unmap_pci_bar;1378 }1379 if (hba->ops->reset_comm(hba)) {1380 printk(KERN_ERR "scsi%d: reset comm failed\n",1381 hba->host->host_no);1382 goto unmap_pci_bar;1383 }1384 }1385 1386 if (hba->firmware_version > 0x01020000 ||1387 hba->interface_version > 0x01020000)1388 hba->iopintf_v2 = 1;1389 1390 host->max_sectors = le32_to_cpu(iop_config.data_transfer_length) >> 9;1391 host->max_id = le32_to_cpu(iop_config.max_devices);1392 host->sg_tablesize = le32_to_cpu(iop_config.max_sg_count);1393 host->can_queue = le32_to_cpu(iop_config.max_requests);1394 host->cmd_per_lun = le32_to_cpu(iop_config.max_requests);1395 host->max_cmd_len = 16;1396 1397 req_size = struct_size_t(struct hpt_iop_request_scsi_command,1398 sg_list, hba->max_sg_descriptors);1399 if ((req_size & 0x1f) != 0)1400 req_size = (req_size + 0x1f) & ~0x1f;1401 1402 memset(&set_config, 0, sizeof(struct hpt_iop_request_set_config));1403 set_config.iop_id = cpu_to_le32(host->host_no);1404 set_config.vbus_id = cpu_to_le16(host->host_no);1405 set_config.max_host_request_size = cpu_to_le16(req_size);1406 1407 if (hba->ops->set_config(hba, &set_config)) {1408 printk(KERN_ERR "scsi%d: set config failed\n",1409 hba->host->host_no);1410 goto unmap_pci_bar;1411 }1412 1413 pci_set_drvdata(pcidev, host);1414 1415 if (request_irq(pcidev->irq, hptiop_intr, IRQF_SHARED,1416 driver_name, hba)) {1417 printk(KERN_ERR "scsi%d: request irq %d failed\n",1418 hba->host->host_no, pcidev->irq);1419 goto unmap_pci_bar;1420 }1421 1422 /* Allocate request mem */1423 1424 dprintk("req_size=%d, max_requests=%d\n", req_size, hba->max_requests);1425 1426 hba->req_size = req_size;1427 hba->req_list = NULL;1428 1429 for (i = 0; i < hba->max_requests; i++) {1430 start_virt = dma_alloc_coherent(&pcidev->dev,1431 hba->req_size + 0x20,1432 &start_phy, GFP_KERNEL);1433 1434 if (!start_virt) {1435 printk(KERN_ERR "scsi%d: fail to alloc request mem\n",1436 hba->host->host_no);1437 goto free_request_mem;1438 }1439 1440 hba->dma_coherent[i] = start_virt;1441 hba->dma_coherent_handle[i] = start_phy;1442 1443 if ((start_phy & 0x1f) != 0) {1444 offset = ((start_phy + 0x1f) & ~0x1f) - start_phy;1445 start_phy += offset;1446 start_virt += offset;1447 }1448 1449 hba->reqs[i].next = NULL;1450 hba->reqs[i].req_virt = start_virt;1451 hba->reqs[i].req_shifted_phy = start_phy >> 5;1452 hba->reqs[i].index = i;1453 free_req(hba, &hba->reqs[i]);1454 }1455 1456 /* Enable Interrupt and start background task */1457 if (hptiop_initialize_iop(hba))1458 goto free_request_mem;1459 1460 if (scsi_add_host(host, &pcidev->dev)) {1461 printk(KERN_ERR "scsi%d: scsi_add_host failed\n",1462 hba->host->host_no);1463 goto free_request_mem;1464 }1465 1466 scsi_scan_host(host);1467 1468 dprintk("scsi%d: hptiop_probe successfully\n", hba->host->host_no);1469 return 0;1470 1471free_request_mem:1472 for (i = 0; i < hba->max_requests; i++) {1473 if (hba->dma_coherent[i] && hba->dma_coherent_handle[i])1474 dma_free_coherent(&hba->pcidev->dev,1475 hba->req_size + 0x20,1476 hba->dma_coherent[i],1477 hba->dma_coherent_handle[i]);1478 else1479 break;1480 }1481 1482 free_irq(hba->pcidev->irq, hba);1483 1484unmap_pci_bar:1485 hba->ops->internal_memfree(hba);1486 1487 hba->ops->unmap_pci_bar(hba);1488 1489free_scsi_host:1490 scsi_host_put(host);1491 1492free_pci_regions:1493 pci_release_regions(pcidev);1494 1495disable_pci_device:1496 pci_disable_device(pcidev);1497 1498 dprintk("scsi%d: hptiop_probe fail\n", host ? host->host_no : 0);1499 return -ENODEV;1500}1501 1502static void hptiop_shutdown(struct pci_dev *pcidev)1503{1504 struct Scsi_Host *host = pci_get_drvdata(pcidev);1505 struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata;1506 1507 dprintk("hptiop_shutdown(%p)\n", hba);1508 1509 /* stop the iop */1510 if (iop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_SHUTDOWN, 60000))1511 printk(KERN_ERR "scsi%d: shutdown the iop timeout\n",1512 hba->host->host_no);1513 1514 /* disable all outbound interrupts */1515 hba->ops->disable_intr(hba);1516}1517 1518static void hptiop_disable_intr_itl(struct hptiop_hba *hba)1519{1520 u32 int_mask;1521 1522 int_mask = readl(&hba->u.itl.iop->outbound_intmask);1523 writel(int_mask |1524 IOPMU_OUTBOUND_INT_MSG0 | IOPMU_OUTBOUND_INT_POSTQUEUE,1525 &hba->u.itl.iop->outbound_intmask);1526 readl(&hba->u.itl.iop->outbound_intmask);1527}1528 1529static void hptiop_disable_intr_mv(struct hptiop_hba *hba)1530{1531 writel(0, &hba->u.mv.regs->outbound_intmask);1532 readl(&hba->u.mv.regs->outbound_intmask);1533}1534 1535static void hptiop_disable_intr_mvfrey(struct hptiop_hba *hba)1536{1537 writel(0, &(hba->u.mvfrey.mu->f0_doorbell_enable));1538 readl(&(hba->u.mvfrey.mu->f0_doorbell_enable));1539 writel(0, &(hba->u.mvfrey.mu->isr_enable));1540 readl(&(hba->u.mvfrey.mu->isr_enable));1541 writel(0, &(hba->u.mvfrey.mu->pcie_f0_int_enable));1542 readl(&(hba->u.mvfrey.mu->pcie_f0_int_enable));1543}1544 1545static void hptiop_remove(struct pci_dev *pcidev)1546{1547 struct Scsi_Host *host = pci_get_drvdata(pcidev);1548 struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata;1549 u32 i;1550 1551 dprintk("scsi%d: hptiop_remove\n", hba->host->host_no);1552 1553 scsi_remove_host(host);1554 1555 hptiop_shutdown(pcidev);1556 1557 free_irq(hba->pcidev->irq, hba);1558 1559 for (i = 0; i < hba->max_requests; i++) {1560 if (hba->dma_coherent[i] && hba->dma_coherent_handle[i])1561 dma_free_coherent(&hba->pcidev->dev,1562 hba->req_size + 0x20,1563 hba->dma_coherent[i],1564 hba->dma_coherent_handle[i]);1565 else1566 break;1567 }1568 1569 hba->ops->internal_memfree(hba);1570 1571 hba->ops->unmap_pci_bar(hba);1572 1573 pci_release_regions(hba->pcidev);1574 pci_set_drvdata(hba->pcidev, NULL);1575 pci_disable_device(hba->pcidev);1576 1577 scsi_host_put(host);1578}1579 1580static struct hptiop_adapter_ops hptiop_itl_ops = {1581 .family = INTEL_BASED_IOP,1582 .iop_wait_ready = iop_wait_ready_itl,1583 .internal_memalloc = hptiop_internal_memalloc_itl,1584 .internal_memfree = hptiop_internal_memfree_itl,1585 .map_pci_bar = hptiop_map_pci_bar_itl,1586 .unmap_pci_bar = hptiop_unmap_pci_bar_itl,1587 .enable_intr = hptiop_enable_intr_itl,1588 .disable_intr = hptiop_disable_intr_itl,1589 .get_config = iop_get_config_itl,1590 .set_config = iop_set_config_itl,1591 .iop_intr = iop_intr_itl,1592 .post_msg = hptiop_post_msg_itl,1593 .post_req = hptiop_post_req_itl,1594 .hw_dma_bit_mask = 64,1595 .reset_comm = hptiop_reset_comm_itl,1596 .host_phy_flag = cpu_to_le64(0),1597};1598 1599static struct hptiop_adapter_ops hptiop_mv_ops = {1600 .family = MV_BASED_IOP,1601 .iop_wait_ready = iop_wait_ready_mv,1602 .internal_memalloc = hptiop_internal_memalloc_mv,1603 .internal_memfree = hptiop_internal_memfree_mv,1604 .map_pci_bar = hptiop_map_pci_bar_mv,1605 .unmap_pci_bar = hptiop_unmap_pci_bar_mv,1606 .enable_intr = hptiop_enable_intr_mv,1607 .disable_intr = hptiop_disable_intr_mv,1608 .get_config = iop_get_config_mv,1609 .set_config = iop_set_config_mv,1610 .iop_intr = iop_intr_mv,1611 .post_msg = hptiop_post_msg_mv,1612 .post_req = hptiop_post_req_mv,1613 .hw_dma_bit_mask = 33,1614 .reset_comm = hptiop_reset_comm_mv,1615 .host_phy_flag = cpu_to_le64(0),1616};1617 1618static struct hptiop_adapter_ops hptiop_mvfrey_ops = {1619 .family = MVFREY_BASED_IOP,1620 .iop_wait_ready = iop_wait_ready_mvfrey,1621 .internal_memalloc = hptiop_internal_memalloc_mvfrey,1622 .internal_memfree = hptiop_internal_memfree_mvfrey,1623 .map_pci_bar = hptiop_map_pci_bar_mvfrey,1624 .unmap_pci_bar = hptiop_unmap_pci_bar_mvfrey,1625 .enable_intr = hptiop_enable_intr_mvfrey,1626 .disable_intr = hptiop_disable_intr_mvfrey,1627 .get_config = iop_get_config_mvfrey,1628 .set_config = iop_set_config_mvfrey,1629 .iop_intr = iop_intr_mvfrey,1630 .post_msg = hptiop_post_msg_mvfrey,1631 .post_req = hptiop_post_req_mvfrey,1632 .hw_dma_bit_mask = 64,1633 .reset_comm = hptiop_reset_comm_mvfrey,1634 .host_phy_flag = cpu_to_le64(1),1635};1636 1637static struct pci_device_id hptiop_id_table[] = {1638 { PCI_VDEVICE(TTI, 0x3220), (kernel_ulong_t)&hptiop_itl_ops },1639 { PCI_VDEVICE(TTI, 0x3320), (kernel_ulong_t)&hptiop_itl_ops },1640 { PCI_VDEVICE(TTI, 0x3410), (kernel_ulong_t)&hptiop_itl_ops },1641 { PCI_VDEVICE(TTI, 0x3510), (kernel_ulong_t)&hptiop_itl_ops },1642 { PCI_VDEVICE(TTI, 0x3511), (kernel_ulong_t)&hptiop_itl_ops },1643 { PCI_VDEVICE(TTI, 0x3520), (kernel_ulong_t)&hptiop_itl_ops },1644 { PCI_VDEVICE(TTI, 0x3521), (kernel_ulong_t)&hptiop_itl_ops },1645 { PCI_VDEVICE(TTI, 0x3522), (kernel_ulong_t)&hptiop_itl_ops },1646 { PCI_VDEVICE(TTI, 0x3530), (kernel_ulong_t)&hptiop_itl_ops },1647 { PCI_VDEVICE(TTI, 0x3540), (kernel_ulong_t)&hptiop_itl_ops },1648 { PCI_VDEVICE(TTI, 0x3560), (kernel_ulong_t)&hptiop_itl_ops },1649 { PCI_VDEVICE(TTI, 0x4210), (kernel_ulong_t)&hptiop_itl_ops },1650 { PCI_VDEVICE(TTI, 0x4211), (kernel_ulong_t)&hptiop_itl_ops },1651 { PCI_VDEVICE(TTI, 0x4310), (kernel_ulong_t)&hptiop_itl_ops },1652 { PCI_VDEVICE(TTI, 0x4311), (kernel_ulong_t)&hptiop_itl_ops },1653 { PCI_VDEVICE(TTI, 0x4320), (kernel_ulong_t)&hptiop_itl_ops },1654 { PCI_VDEVICE(TTI, 0x4321), (kernel_ulong_t)&hptiop_itl_ops },1655 { PCI_VDEVICE(TTI, 0x4322), (kernel_ulong_t)&hptiop_itl_ops },1656 { PCI_VDEVICE(TTI, 0x4400), (kernel_ulong_t)&hptiop_itl_ops },1657 { PCI_VDEVICE(TTI, 0x3120), (kernel_ulong_t)&hptiop_mv_ops },1658 { PCI_VDEVICE(TTI, 0x3122), (kernel_ulong_t)&hptiop_mv_ops },1659 { PCI_VDEVICE(TTI, 0x3020), (kernel_ulong_t)&hptiop_mv_ops },1660 { PCI_VDEVICE(TTI, 0x4520), (kernel_ulong_t)&hptiop_mvfrey_ops },1661 { PCI_VDEVICE(TTI, 0x4522), (kernel_ulong_t)&hptiop_mvfrey_ops },1662 { PCI_VDEVICE(TTI, 0x3610), (kernel_ulong_t)&hptiop_mvfrey_ops },1663 { PCI_VDEVICE(TTI, 0x3611), (kernel_ulong_t)&hptiop_mvfrey_ops },1664 { PCI_VDEVICE(TTI, 0x3620), (kernel_ulong_t)&hptiop_mvfrey_ops },1665 { PCI_VDEVICE(TTI, 0x3622), (kernel_ulong_t)&hptiop_mvfrey_ops },1666 { PCI_VDEVICE(TTI, 0x3640), (kernel_ulong_t)&hptiop_mvfrey_ops },1667 { PCI_VDEVICE(TTI, 0x3660), (kernel_ulong_t)&hptiop_mvfrey_ops },1668 { PCI_VDEVICE(TTI, 0x3680), (kernel_ulong_t)&hptiop_mvfrey_ops },1669 { PCI_VDEVICE(TTI, 0x3690), (kernel_ulong_t)&hptiop_mvfrey_ops },1670 {},1671};1672 1673MODULE_DEVICE_TABLE(pci, hptiop_id_table);1674 1675static struct pci_driver hptiop_pci_driver = {1676 .name = driver_name,1677 .id_table = hptiop_id_table,1678 .probe = hptiop_probe,1679 .remove = hptiop_remove,1680 .shutdown = hptiop_shutdown,1681};1682 1683static int __init hptiop_module_init(void)1684{1685 printk(KERN_INFO "%s %s\n", driver_name_long, driver_ver);1686 return pci_register_driver(&hptiop_pci_driver);1687}1688 1689static void __exit hptiop_module_exit(void)1690{1691 pci_unregister_driver(&hptiop_pci_driver);1692}1693 1694 1695module_init(hptiop_module_init);1696module_exit(hptiop_module_exit);1697 1698MODULE_LICENSE("GPL");1699 1700