| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /*************************************************************************** |
|---|
| 2 | 3 | dpti.c - description |
|---|
| 3 | 4 | ------------------- |
|---|
| .. | .. |
|---|
| 7 | 8 | July 30, 2001 First version being submitted |
|---|
| 8 | 9 | for inclusion in the kernel. V2.4 |
|---|
| 9 | 10 | |
|---|
| 10 | | - See Documentation/scsi/dpti.txt for history, notes, license info |
|---|
| 11 | + See Documentation/scsi/dpti.rst for history, notes, license info |
|---|
| 11 | 12 | and credits |
|---|
| 12 | 13 | ***************************************************************************/ |
|---|
| 13 | 14 | |
|---|
| 14 | 15 | /*************************************************************************** |
|---|
| 15 | 16 | * * |
|---|
| 16 | | - * This program is free software; you can redistribute it and/or modify * |
|---|
| 17 | | - * it under the terms of the GNU General Public License as published by * |
|---|
| 18 | | - * the Free Software Foundation; either version 2 of the License, or * |
|---|
| 19 | | - * (at your option) any later version. * |
|---|
| 20 | 17 | * * |
|---|
| 21 | 18 | ***************************************************************************/ |
|---|
| 22 | 19 | /*************************************************************************** |
|---|
| .. | .. |
|---|
| 30 | 27 | /*#define UARTDELAY 1 */ |
|---|
| 31 | 28 | |
|---|
| 32 | 29 | #include <linux/module.h> |
|---|
| 30 | +#include <linux/pgtable.h> |
|---|
| 33 | 31 | |
|---|
| 34 | 32 | MODULE_AUTHOR("Deanna Bonds, with _lots_ of help from Mark Salyzyn"); |
|---|
| 35 | 33 | MODULE_DESCRIPTION("Adaptec I2O RAID Driver"); |
|---|
| .. | .. |
|---|
| 58 | 56 | #include <linux/mutex.h> |
|---|
| 59 | 57 | |
|---|
| 60 | 58 | #include <asm/processor.h> /* for boot_cpu_data */ |
|---|
| 61 | | -#include <asm/pgtable.h> |
|---|
| 62 | 59 | #include <asm/io.h> /* for virt_to_bus, etc. */ |
|---|
| 63 | 60 | |
|---|
| 64 | 61 | #include <scsi/scsi.h> |
|---|
| .. | .. |
|---|
| 411 | 408 | static int adpt_slave_configure(struct scsi_device * device) |
|---|
| 412 | 409 | { |
|---|
| 413 | 410 | struct Scsi_Host *host = device->host; |
|---|
| 414 | | - adpt_hba* pHba; |
|---|
| 415 | | - |
|---|
| 416 | | - pHba = (adpt_hba *) host->hostdata[0]; |
|---|
| 417 | 411 | |
|---|
| 418 | 412 | if (host->can_queue && device->tagged_supported) { |
|---|
| 419 | 413 | scsi_change_queue_depth(device, |
|---|
| .. | .. |
|---|
| 589 | 583 | } |
|---|
| 590 | 584 | |
|---|
| 591 | 585 | /* |
|---|
| 592 | | - * Turn a struct scsi_cmnd * into a unique 32 bit 'context'. |
|---|
| 593 | | - */ |
|---|
| 594 | | -static u32 adpt_cmd_to_context(struct scsi_cmnd *cmd) |
|---|
| 595 | | -{ |
|---|
| 596 | | - return (u32)cmd->serial_number; |
|---|
| 597 | | -} |
|---|
| 598 | | - |
|---|
| 599 | | -/* |
|---|
| 600 | | - * Go from a u32 'context' to a struct scsi_cmnd * . |
|---|
| 601 | | - * This could probably be made more efficient. |
|---|
| 602 | | - */ |
|---|
| 603 | | -static struct scsi_cmnd * |
|---|
| 604 | | - adpt_cmd_from_context(adpt_hba * pHba, u32 context) |
|---|
| 605 | | -{ |
|---|
| 606 | | - struct scsi_cmnd * cmd; |
|---|
| 607 | | - struct scsi_device * d; |
|---|
| 608 | | - |
|---|
| 609 | | - if (context == 0) |
|---|
| 610 | | - return NULL; |
|---|
| 611 | | - |
|---|
| 612 | | - spin_unlock(pHba->host->host_lock); |
|---|
| 613 | | - shost_for_each_device(d, pHba->host) { |
|---|
| 614 | | - unsigned long flags; |
|---|
| 615 | | - spin_lock_irqsave(&d->list_lock, flags); |
|---|
| 616 | | - list_for_each_entry(cmd, &d->cmd_list, list) { |
|---|
| 617 | | - if (((u32)cmd->serial_number == context)) { |
|---|
| 618 | | - spin_unlock_irqrestore(&d->list_lock, flags); |
|---|
| 619 | | - scsi_device_put(d); |
|---|
| 620 | | - spin_lock(pHba->host->host_lock); |
|---|
| 621 | | - return cmd; |
|---|
| 622 | | - } |
|---|
| 623 | | - } |
|---|
| 624 | | - spin_unlock_irqrestore(&d->list_lock, flags); |
|---|
| 625 | | - } |
|---|
| 626 | | - spin_lock(pHba->host->host_lock); |
|---|
| 627 | | - |
|---|
| 628 | | - return NULL; |
|---|
| 629 | | -} |
|---|
| 630 | | - |
|---|
| 631 | | -/* |
|---|
| 632 | 586 | * Turn a pointer to ioctl reply data into an u32 'context' |
|---|
| 633 | 587 | */ |
|---|
| 634 | 588 | static u32 adpt_ioctl_to_context(adpt_hba * pHba, void *reply) |
|---|
| .. | .. |
|---|
| 685 | 639 | u32 msg[5]; |
|---|
| 686 | 640 | int rcode; |
|---|
| 687 | 641 | |
|---|
| 688 | | - if(cmd->serial_number == 0){ |
|---|
| 689 | | - return FAILED; |
|---|
| 690 | | - } |
|---|
| 691 | 642 | pHba = (adpt_hba*) cmd->device->host->hostdata[0]; |
|---|
| 692 | 643 | printk(KERN_INFO"%s: Trying to Abort\n",pHba->name); |
|---|
| 693 | 644 | if ((dptdevice = (void*) (cmd->device->hostdata)) == NULL) { |
|---|
| .. | .. |
|---|
| 699 | 650 | msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0; |
|---|
| 700 | 651 | msg[1] = I2O_CMD_SCSI_ABORT<<24|HOST_TID<<12|dptdevice->tid; |
|---|
| 701 | 652 | msg[2] = 0; |
|---|
| 702 | | - msg[3]= 0; |
|---|
| 703 | | - msg[4] = adpt_cmd_to_context(cmd); |
|---|
| 653 | + msg[3]= 0; |
|---|
| 654 | + /* Add 1 to avoid firmware treating it as invalid command */ |
|---|
| 655 | + msg[4] = cmd->request->tag + 1; |
|---|
| 704 | 656 | if (pHba->host) |
|---|
| 705 | 657 | spin_lock_irq(pHba->host->host_lock); |
|---|
| 706 | 658 | rcode = adpt_i2o_post_wait(pHba, msg, sizeof(msg), FOREVER); |
|---|
| .. | .. |
|---|
| 862 | 814 | } |
|---|
| 863 | 815 | pHba->state &= ~DPTI_STATE_RESET; |
|---|
| 864 | 816 | |
|---|
| 865 | | - adpt_fail_posted_scbs(pHba); |
|---|
| 817 | + scsi_host_complete_all_commands(pHba->host, DID_RESET); |
|---|
| 866 | 818 | return 0; /* return success */ |
|---|
| 867 | 819 | } |
|---|
| 868 | 820 | |
|---|
| .. | .. |
|---|
| 877 | 829 | adpt_hba *pHba, *pNext; |
|---|
| 878 | 830 | struct adpt_i2o_post_wait_data *p1, *old; |
|---|
| 879 | 831 | |
|---|
| 880 | | - printk(KERN_INFO"Shutting down Adaptec I2O controllers.\n"); |
|---|
| 881 | | - printk(KERN_INFO" This could take a few minutes if there are many devices attached\n"); |
|---|
| 832 | + printk(KERN_INFO "Shutting down Adaptec I2O controllers.\n"); |
|---|
| 833 | + printk(KERN_INFO " This could take a few minutes if there are many devices attached\n"); |
|---|
| 882 | 834 | /* Delete all IOPs from the controller chain */ |
|---|
| 883 | 835 | /* They should have already been released by the |
|---|
| 884 | 836 | * scsi-core |
|---|
| .. | .. |
|---|
| 901 | 853 | // spin_unlock_irqrestore(&adpt_post_wait_lock, flags); |
|---|
| 902 | 854 | adpt_post_wait_queue = NULL; |
|---|
| 903 | 855 | |
|---|
| 904 | | - printk(KERN_INFO "Adaptec I2O controllers down.\n"); |
|---|
| 856 | + printk(KERN_INFO "Adaptec I2O controllers down.\n"); |
|---|
| 905 | 857 | } |
|---|
| 906 | 858 | |
|---|
| 907 | 859 | static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev) |
|---|
| .. | .. |
|---|
| 934 | 886 | * See if we should enable dma64 mode. |
|---|
| 935 | 887 | */ |
|---|
| 936 | 888 | if (sizeof(dma_addr_t) > 4 && |
|---|
| 937 | | - pci_set_dma_mask(pDev, DMA_BIT_MASK(64)) == 0) { |
|---|
| 938 | | - if (dma_get_required_mask(&pDev->dev) > DMA_BIT_MASK(32)) |
|---|
| 939 | | - dma64 = 1; |
|---|
| 940 | | - } |
|---|
| 941 | | - if (!dma64 && pci_set_dma_mask(pDev, DMA_BIT_MASK(32)) != 0) |
|---|
| 889 | + dma_get_required_mask(&pDev->dev) > DMA_BIT_MASK(32) && |
|---|
| 890 | + dma_set_mask(&pDev->dev, DMA_BIT_MASK(64)) == 0) |
|---|
| 891 | + dma64 = 1; |
|---|
| 892 | + |
|---|
| 893 | + if (!dma64 && dma_set_mask(&pDev->dev, DMA_BIT_MASK(32)) != 0) |
|---|
| 942 | 894 | return -EINVAL; |
|---|
| 943 | 895 | |
|---|
| 944 | 896 | /* adapter only supports message blocks below 4GB */ |
|---|
| 945 | | - pci_set_consistent_dma_mask(pDev, DMA_BIT_MASK(32)); |
|---|
| 897 | + dma_set_coherent_mask(&pDev->dev, DMA_BIT_MASK(32)); |
|---|
| 946 | 898 | |
|---|
| 947 | 899 | base_addr0_phys = pci_resource_start(pDev,0); |
|---|
| 948 | 900 | hba_map0_area_size = pci_resource_len(pDev,0); |
|---|
| .. | .. |
|---|
| 1165 | 1117 | { |
|---|
| 1166 | 1118 | struct adpt_device* d; |
|---|
| 1167 | 1119 | |
|---|
| 1168 | | - if(chan < 0 || chan >= MAX_CHANNEL) |
|---|
| 1120 | + if (chan >= MAX_CHANNEL) |
|---|
| 1169 | 1121 | return NULL; |
|---|
| 1170 | 1122 | |
|---|
| 1171 | 1123 | d = pHba->channel[chan].device[id]; |
|---|
| .. | .. |
|---|
| 1376 | 1328 | printk(KERN_ERR"IOP reset failed - no free memory.\n"); |
|---|
| 1377 | 1329 | return -ENOMEM; |
|---|
| 1378 | 1330 | } |
|---|
| 1379 | | - memset(status,0,4); |
|---|
| 1380 | 1331 | |
|---|
| 1381 | 1332 | msg[0]=EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0; |
|---|
| 1382 | 1333 | msg[1]=I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID; |
|---|
| .. | .. |
|---|
| 2198 | 2149 | status = I2O_POST_WAIT_OK; |
|---|
| 2199 | 2150 | } |
|---|
| 2200 | 2151 | if(!(context & 0x40000000)) { |
|---|
| 2201 | | - cmd = adpt_cmd_from_context(pHba, |
|---|
| 2202 | | - readl(reply+12)); |
|---|
| 2152 | + /* |
|---|
| 2153 | + * The request tag is one less than the command tag |
|---|
| 2154 | + * as the firmware might treat a 0 tag as invalid |
|---|
| 2155 | + */ |
|---|
| 2156 | + cmd = scsi_host_find_tag(pHba->host, |
|---|
| 2157 | + readl(reply + 12) - 1); |
|---|
| 2203 | 2158 | if(cmd != NULL) { |
|---|
| 2204 | 2159 | printk(KERN_WARNING"%s: Apparent SCSI cmd in Post Wait Context - cmd=%p context=%x\n", pHba->name, cmd, context); |
|---|
| 2205 | 2160 | } |
|---|
| 2206 | 2161 | } |
|---|
| 2207 | 2162 | adpt_i2o_post_wait_complete(context, status); |
|---|
| 2208 | 2163 | } else { // SCSI message |
|---|
| 2209 | | - cmd = adpt_cmd_from_context (pHba, readl(reply+12)); |
|---|
| 2164 | + /* |
|---|
| 2165 | + * The request tag is one less than the command tag |
|---|
| 2166 | + * as the firmware might treat a 0 tag as invalid |
|---|
| 2167 | + */ |
|---|
| 2168 | + cmd = scsi_host_find_tag(pHba->host, |
|---|
| 2169 | + readl(reply + 12) - 1); |
|---|
| 2210 | 2170 | if(cmd != NULL){ |
|---|
| 2211 | 2171 | scsi_dma_unmap(cmd); |
|---|
| 2212 | | - if(cmd->serial_number != 0) { // If not timedout |
|---|
| 2213 | | - adpt_i2o_to_scsi(reply, cmd); |
|---|
| 2214 | | - } |
|---|
| 2172 | + adpt_i2o_scsi_complete(reply, cmd); |
|---|
| 2215 | 2173 | } |
|---|
| 2216 | 2174 | } |
|---|
| 2217 | 2175 | writel(m, pHba->reply_port); |
|---|
| .. | .. |
|---|
| 2277 | 2235 | // I2O_CMD_SCSI_EXEC |
|---|
| 2278 | 2236 | msg[1] = ((0xff<<24)|(HOST_TID<<12)|d->tid); |
|---|
| 2279 | 2237 | msg[2] = 0; |
|---|
| 2280 | | - msg[3] = adpt_cmd_to_context(cmd); /* Want SCSI control block back */ |
|---|
| 2238 | + /* Add 1 to avoid firmware treating it as invalid command */ |
|---|
| 2239 | + msg[3] = cmd->request->tag + 1; |
|---|
| 2281 | 2240 | // Our cards use the transaction context as the tag for queueing |
|---|
| 2282 | 2241 | // Adaptec/DPT Private stuff |
|---|
| 2283 | 2242 | msg[4] = I2O_CMD_SCSI_EXEC|(DPT_ORGANIZATION_ID<<16); |
|---|
| .. | .. |
|---|
| 2372 | 2331 | host->unique_id = (u32)sys_tbl_pa + pHba->unit; |
|---|
| 2373 | 2332 | host->sg_tablesize = pHba->sg_tablesize; |
|---|
| 2374 | 2333 | host->can_queue = pHba->post_fifo_size; |
|---|
| 2375 | | - host->use_cmd_list = 1; |
|---|
| 2376 | 2334 | |
|---|
| 2377 | 2335 | return 0; |
|---|
| 2378 | 2336 | } |
|---|
| 2379 | 2337 | |
|---|
| 2380 | 2338 | |
|---|
| 2381 | | -static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd) |
|---|
| 2339 | +static void adpt_i2o_scsi_complete(void __iomem *reply, struct scsi_cmnd *cmd) |
|---|
| 2382 | 2340 | { |
|---|
| 2383 | 2341 | adpt_hba* pHba; |
|---|
| 2384 | 2342 | u32 hba_status; |
|---|
| .. | .. |
|---|
| 2496 | 2454 | if(cmd->scsi_done != NULL){ |
|---|
| 2497 | 2455 | cmd->scsi_done(cmd); |
|---|
| 2498 | 2456 | } |
|---|
| 2499 | | - return cmd->result; |
|---|
| 2500 | 2457 | } |
|---|
| 2501 | 2458 | |
|---|
| 2502 | 2459 | |
|---|
| .. | .. |
|---|
| 2684 | 2641 | return 0; |
|---|
| 2685 | 2642 | } |
|---|
| 2686 | 2643 | |
|---|
| 2687 | | -static void adpt_fail_posted_scbs(adpt_hba* pHba) |
|---|
| 2688 | | -{ |
|---|
| 2689 | | - struct scsi_cmnd* cmd = NULL; |
|---|
| 2690 | | - struct scsi_device* d = NULL; |
|---|
| 2691 | | - |
|---|
| 2692 | | - shost_for_each_device(d, pHba->host) { |
|---|
| 2693 | | - unsigned long flags; |
|---|
| 2694 | | - spin_lock_irqsave(&d->list_lock, flags); |
|---|
| 2695 | | - list_for_each_entry(cmd, &d->cmd_list, list) { |
|---|
| 2696 | | - if(cmd->serial_number == 0){ |
|---|
| 2697 | | - continue; |
|---|
| 2698 | | - } |
|---|
| 2699 | | - cmd->result = (DID_OK << 16) | (QUEUE_FULL <<1); |
|---|
| 2700 | | - cmd->scsi_done(cmd); |
|---|
| 2701 | | - } |
|---|
| 2702 | | - spin_unlock_irqrestore(&d->list_lock, flags); |
|---|
| 2703 | | - } |
|---|
| 2704 | | -} |
|---|
| 2705 | | - |
|---|
| 2706 | | - |
|---|
| 2707 | 2644 | /*============================================================================ |
|---|
| 2708 | 2645 | * Routines from i2o subsystem |
|---|
| 2709 | 2646 | *============================================================================ |
|---|
| .. | .. |
|---|
| 2843 | 2780 | pHba->name); |
|---|
| 2844 | 2781 | return -ENOMEM; |
|---|
| 2845 | 2782 | } |
|---|
| 2846 | | - memset(status, 0, 4); |
|---|
| 2847 | 2783 | |
|---|
| 2848 | 2784 | writel(EIGHT_WORD_MSG_SIZE| SGL_OFFSET_6, &msg[0]); |
|---|
| 2849 | 2785 | writel(I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID, &msg[1]); |
|---|
| .. | .. |
|---|
| 2897 | 2833 | printk(KERN_ERR "%s: Could not allocate reply pool\n", pHba->name); |
|---|
| 2898 | 2834 | return -ENOMEM; |
|---|
| 2899 | 2835 | } |
|---|
| 2900 | | - memset(pHba->reply_pool, 0 , pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4); |
|---|
| 2901 | 2836 | |
|---|
| 2902 | 2837 | for(i = 0; i < pHba->reply_fifo_size; i++) { |
|---|
| 2903 | 2838 | writel(pHba->reply_pool_pa + (i * REPLY_FRAME_SIZE * 4), |
|---|
| .. | .. |
|---|
| 3132 | 3067 | printk(KERN_WARNING "SysTab Set failed. Out of memory.\n"); |
|---|
| 3133 | 3068 | return -ENOMEM; |
|---|
| 3134 | 3069 | } |
|---|
| 3135 | | - memset(sys_tbl, 0, sys_tbl_len); |
|---|
| 3136 | 3070 | |
|---|
| 3137 | 3071 | sys_tbl->num_entries = hba_count; |
|---|
| 3138 | 3072 | sys_tbl->version = I2OVERSION; |
|---|
| .. | .. |
|---|
| 3427 | 3361 | return -((res[1] >> 16) & 0xFF); /* -BlockStatus */ |
|---|
| 3428 | 3362 | } |
|---|
| 3429 | 3363 | |
|---|
| 3430 | | - return 4 + ((res[1] & 0x0000FFFF) << 2); /* bytes used in resblk */ |
|---|
| 3364 | + return 4 + ((res[1] & 0x0000FFFF) << 2); /* bytes used in resblk */ |
|---|
| 3431 | 3365 | } |
|---|
| 3432 | 3366 | |
|---|
| 3433 | 3367 | |
|---|
| .. | .. |
|---|
| 3500 | 3434 | |
|---|
| 3501 | 3435 | static int adpt_i2o_systab_send(adpt_hba* pHba) |
|---|
| 3502 | 3436 | { |
|---|
| 3503 | | - u32 msg[12]; |
|---|
| 3504 | | - int ret; |
|---|
| 3437 | + u32 msg[12]; |
|---|
| 3438 | + int ret; |
|---|
| 3505 | 3439 | |
|---|
| 3506 | 3440 | msg[0] = I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6; |
|---|
| 3507 | 3441 | msg[1] = I2O_CMD_SYS_TAB_SET<<24 | HOST_TID<<12 | ADAPTER_TID; |
|---|
| .. | .. |
|---|
| 3569 | 3503 | .slave_configure = adpt_slave_configure, |
|---|
| 3570 | 3504 | .can_queue = MAX_TO_IOP_MESSAGES, |
|---|
| 3571 | 3505 | .this_id = 7, |
|---|
| 3572 | | - .use_clustering = ENABLE_CLUSTERING, |
|---|
| 3573 | 3506 | }; |
|---|
| 3574 | 3507 | |
|---|
| 3575 | 3508 | static int __init adpt_init(void) |
|---|