X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fscsi%2Flpfc%2Flpfc_mbox.c;h=4d016c2a1b26ebd14a8eb577d73c2c809bdd1337;hb=refs%2Fheads%2Fvserver;hp=436d1b7c54c62130151f388de5e0450289b25c14;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 436d1b7c5..4d016c2a1 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -1,40 +1,40 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * - * Enterprise Fibre Channel Host Bus Adapters. * - * Refer to the README file included with this package for * - * driver version and adapter support. * - * Copyright (C) 2004 Emulex Corporation. * + * Fibre Channel Host Bus Adapters. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * + * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * + * Portions Copyright (C) 2004-2005 Christoph Hellwig * * * * This program is free software; you can redistribute it and/or * - * modify it under the terms of the GNU General Public License * - * as published by the Free Software Foundation; either version 2 * - * of the License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details, a copy of which * - * can be found in the file COPYING included with this package. * + * modify it under the terms of version 2 of the GNU General * + * Public License as published by the Free Software Foundation. * + * This program is distributed in the hope that it will be useful. * + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * + * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * + * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * + * TO BE LEGALLY INVALID. See the GNU General Public License for * + * more details, a copy of which can be found in the file COPYING * + * included with this package. * *******************************************************************/ -/* - * $Id: lpfc_mbox.c 1.70 2004/11/18 17:33:04EST sf_support Exp $ - */ -#include #include -#include #include -#include +#include + #include +#include + +#include + +#include "lpfc_hw.h" #include "lpfc_sli.h" #include "lpfc_disc.h" #include "lpfc_scsi.h" #include "lpfc.h" -#include "lpfc_crtn.h" -#include "lpfc_hw.h" #include "lpfc_logmsg.h" -#include "lpfc_mem.h" +#include "lpfc_crtn.h" #include "lpfc_compat.h" /**********************************************/ @@ -42,21 +42,25 @@ /* mailbox command */ /**********************************************/ void -lpfc_dump_mem(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) +lpfc_dump_mem(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, uint16_t offset) { MAILBOX_t *mb; + void *ctx; mb = &pmb->mb; + ctx = pmb->context2; + /* Setup to dump VPD region */ memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); mb->mbxCommand = MBX_DUMP_MEMORY; mb->un.varDmp.cv = 1; mb->un.varDmp.type = DMP_NV_PARAMS; + mb->un.varDmp.entry_index = offset; mb->un.varDmp.region_id = DMP_REGION_VPD; - mb->un.varDmp.word_cnt = (DMP_VPD_SIZE / sizeof (uint32_t)); - + mb->un.varDmp.word_cnt = (DMP_RSP_SIZE / sizeof (uint32_t)); mb->un.varDmp.co = 0; mb->un.varDmp.resp_offset = 0; + pmb->context2 = ctx; mb->mbxOwner = OWN_HOST; return; } @@ -82,40 +86,21 @@ lpfc_read_nv(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) /* mailbox command */ /**********************************************/ int -lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) +lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, struct lpfc_dmabuf *mp) { MAILBOX_t *mb; - struct lpfc_dmabuf *mp; struct lpfc_sli *psli; psli = &phba->sli; mb = &pmb->mb; memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); - /* Get a buffer to hold the loop map */ - if (((mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_ATOMIC)) == 0) || - ((mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys))) == 0)) { - if (mp) - kfree(mp); - mb->mbxCommand = MBX_READ_LA64; - /* READ_LA: no buffers */ - lpfc_printf_log(phba, - KERN_WARNING, - LOG_MBOX, - "%d:0300 READ_LA: no buffers\n", - phba->brd_no); - return (1); - } INIT_LIST_HEAD(&mp->list); mb->mbxCommand = MBX_READ_LA64; mb->un.varReadLA.un.lilpBde64.tus.f.bdeSize = 128; mb->un.varReadLA.un.lilpBde64.addrHigh = putPaddrHigh(mp->phys); mb->un.varReadLA.un.lilpBde64.addrLow = putPaddrLow(mp->phys); - /* Sync the mailbox data with its PCI memory address now. */ - pci_dma_sync_single_for_device(phba->pcidev, mp->phys, LPFC_BPL_SIZE, - PCI_DMA_TODEVICE); - /* Save address for later completion and set the owner to host so that * the FW knows this mailbox is available for processing. */ @@ -210,8 +195,14 @@ lpfc_init_link(struct lpfc_hba * phba, mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT; mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER; break; + case FLAGS_LOCAL_LB: + mb->un.varInitLnk.link_flags = FLAGS_LOCAL_LB; + break; } + /* Enable asynchronous ABTS responses from firmware */ + mb->un.varInitLnk.link_flags |= FLAGS_IMED_ABORT; + /* NEW_FEATURE * Setting up the link speed */ @@ -221,17 +212,17 @@ lpfc_init_link(struct lpfc_hba * phba, case LINK_SPEED_1G: case LINK_SPEED_2G: case LINK_SPEED_4G: - mb->un.varInitLnk.link_flags |= + mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED; mb->un.varInitLnk.link_speed = linkspeed; break; case LINK_SPEED_AUTO: default: - mb->un.varInitLnk.link_speed = + mb->un.varInitLnk.link_speed = LINK_SPEED_AUTO; break; } - + } else mb->un.varInitLnk.link_speed = LINK_SPEED_AUTO; @@ -261,10 +252,9 @@ lpfc_read_sparam(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) /* Get a buffer to hold the HBAs Service Parameters */ - if (((mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_ATOMIC)) == 0) || + if (((mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL)) == 0) || ((mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys))) == 0)) { - if (mp) - kfree(mp); + kfree(mp); mb->mbxCommand = MBX_READ_SPARM64; /* READ_SPARAM: no buffers */ lpfc_printf_log(phba, @@ -280,9 +270,6 @@ lpfc_read_sparam(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) mb->un.varRdSparm.un.sp64.addrHigh = putPaddrHigh(mp->phys); mb->un.varRdSparm.un.sp64.addrLow = putPaddrLow(mp->phys); - pci_dma_sync_single_for_device(phba->pcidev, mp->phys, LPFC_BPL_SIZE, - PCI_DMA_TODEVICE); - /* save address for completion */ pmb->context1 = mp; @@ -308,49 +295,36 @@ lpfc_unreg_did(struct lpfc_hba * phba, uint32_t did, LPFC_MBOXQ_t * pmb) return; } -/***********************************************/ - -/* command to write slim */ -/***********************************************/ +/**********************************************/ +/* lpfc_read_nv Issue a READ CONFIG */ +/* mailbox command */ +/**********************************************/ void -lpfc_set_slim(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, uint32_t addr, - uint32_t value) +lpfc_read_config(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) { MAILBOX_t *mb; mb = &pmb->mb; memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); - /* addr = 0x090597 is AUTO ABTS disable for ELS commands */ - /* addr = 0x052198 is DELAYED ABTS enable for ELS commands */ - - /* - * Always turn on DELAYED ABTS for ELS timeouts - */ - if ((addr == 0x052198) && (value == 0)) - value = 1; - - mb->un.varWords[0] = addr; - mb->un.varWords[1] = value; - - mb->mbxCommand = MBX_SET_SLIM; + mb->mbxCommand = MBX_READ_CONFIG; mb->mbxOwner = OWN_HOST; return; } -/**********************************************/ -/* lpfc_read_nv Issue a READ CONFIG */ -/* mailbox command */ -/**********************************************/ +/*************************************************/ +/* lpfc_read_lnk_stat Issue a READ LINK STATUS */ +/* mailbox command */ +/*************************************************/ void -lpfc_read_config(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) +lpfc_read_lnk_stat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) { MAILBOX_t *mb; mb = &pmb->mb; memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); - mb->mbxCommand = MBX_READ_CONFIG; + mb->mbxCommand = MBX_READ_LNK_STAT; mb->mbxOwner = OWN_HOST; return; } @@ -379,11 +353,9 @@ lpfc_reg_login(struct lpfc_hba * phba, mb->mbxOwner = OWN_HOST; /* Get a buffer to hold NPorts Service Parameters */ - if (((mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_ATOMIC)) == 0) || + if (((mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL)) == NULL) || ((mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys))) == 0)) { - if (mp) - kfree(mp); - + kfree(mp); mb->mbxCommand = MBX_REG_LOGIN64; /* REG_LOGIN: no buffers */ lpfc_printf_log(phba, @@ -400,10 +372,6 @@ lpfc_reg_login(struct lpfc_hba * phba, /* Copy param's into a new buffer */ memcpy(sparam, param, sizeof (struct serv_parm)); - /* Sync the mailbox data with its PCI memory address now. */ - pci_dma_sync_single_for_device(phba->pcidev, mp->phys, LPFC_BPL_SIZE, - PCI_DMA_TODEVICE); - /* save address for completion */ pmb->context1 = (uint8_t *) mp; @@ -441,22 +409,19 @@ lpfc_config_pcb_setup(struct lpfc_hba * phba) struct lpfc_sli *psli = &phba->sli; struct lpfc_sli_ring *pring; PCB_t *pcbp = &phba->slim2p->pcb; - LPFC_RING_INIT_t *pringinit; dma_addr_t pdma_addr; uint32_t offset; uint32_t iocbCnt; int i; - psli->MBhostaddr = (uint32_t *)&phba->slim2p->mbx; - pcbp->maxRing = (psli->sliinit.num_rings - 1); + pcbp->maxRing = (psli->num_rings - 1); iocbCnt = 0; - for (i = 0; i < psli->sliinit.num_rings; i++) { - pringinit = &psli->sliinit.ringinit[i]; + for (i = 0; i < psli->num_rings; i++) { pring = &psli->ring[i]; /* A ring MUST have both cmd and rsp entries defined to be valid */ - if ((pringinit->numCiocb == 0) || (pringinit->numRiocb == 0)) { + if ((pring->numCiocb == 0) || (pring->numRiocb == 0)) { pcbp->rdsc[i].cmdEntries = 0; pcbp->rdsc[i].rspEntries = 0; pcbp->rdsc[i].cmdAddrHigh = 0; @@ -470,26 +435,26 @@ lpfc_config_pcb_setup(struct lpfc_hba * phba) /* Command ring setup for ring */ pring->cmdringaddr = (void *)&phba->slim2p->IOCBs[iocbCnt]; - pcbp->rdsc[i].cmdEntries = pringinit->numCiocb; + pcbp->rdsc[i].cmdEntries = pring->numCiocb; offset = (uint8_t *)&phba->slim2p->IOCBs[iocbCnt] - (uint8_t *)phba->slim2p; pdma_addr = phba->slim2p_mapping + offset; pcbp->rdsc[i].cmdAddrHigh = putPaddrHigh(pdma_addr); pcbp->rdsc[i].cmdAddrLow = putPaddrLow(pdma_addr); - iocbCnt += pringinit->numCiocb; + iocbCnt += pring->numCiocb; /* Response ring setup for ring */ pring->rspringaddr = (void *)&phba->slim2p->IOCBs[iocbCnt]; - pcbp->rdsc[i].rspEntries = pringinit->numRiocb; + pcbp->rdsc[i].rspEntries = pring->numRiocb; offset = (uint8_t *)&phba->slim2p->IOCBs[iocbCnt] - (uint8_t *)phba->slim2p; pdma_addr = phba->slim2p_mapping + offset; pcbp->rdsc[i].rspAddrHigh = putPaddrHigh(pdma_addr); pcbp->rdsc[i].rspAddrLow = putPaddrLow(pdma_addr); - iocbCnt += pringinit->numRiocb; + iocbCnt += pring->numRiocb; } } @@ -512,7 +477,7 @@ lpfc_config_ring(struct lpfc_hba * phba, int ring, LPFC_MBOXQ_t * pmb) int i; MAILBOX_t *mb = &pmb->mb; struct lpfc_sli *psli; - LPFC_RING_INIT_t *pring; + struct lpfc_sli_ring *pring; memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); @@ -522,7 +487,7 @@ lpfc_config_ring(struct lpfc_hba * phba, int ring, LPFC_MBOXQ_t * pmb) mb->un.varCfgRing.recvNotify = 1; psli = &phba->sli; - pring = &psli->sliinit.ringinit[ring]; + pring = &psli->ring[ring]; mb->un.varCfgRing.numMask = pring->num_mask; mb->mbxCommand = MBX_CONFIG_RING; mb->mbxOwner = OWN_HOST; @@ -554,14 +519,16 @@ lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) dma_addr_t pdma_addr; uint32_t bar_low, bar_high; size_t offset; - HGP hgp; - void *to_slim; + struct lpfc_hgp hgp; + void __iomem *to_slim; + int i; memset(pmb, 0, sizeof(LPFC_MBOXQ_t)); mb->mbxCommand = MBX_CONFIG_PORT; mb->mbxOwner = OWN_HOST; mb->un.varCfgPort.pcbLen = sizeof(PCB_t); + offset = (uint8_t *)&phba->slim2p->pcb - (uint8_t *)phba->slim2p; pdma_addr = phba->slim2p_mapping + offset; mb->un.varCfgPort.pcbLow = putPaddrLow(pdma_addr); @@ -595,7 +562,7 @@ lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) * value of pci_resource_start() as the OS value may be a cookie * for ioremap/iomap. */ - + pci_read_config_dword(phba->pcidev, PCI_BASE_ADDRESS_0, &bar_low); pci_read_config_dword(phba->pcidev, PCI_BASE_ADDRESS_1, &bar_high); @@ -606,12 +573,16 @@ lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) (SLIMOFF*sizeof(uint32_t)); if (bar_low & PCI_BASE_ADDRESS_MEM_TYPE_64) phba->slim2p->pcb.hgpAddrHigh = bar_high; - else + else phba->slim2p->pcb.hgpAddrHigh = 0; /* write HGP data to SLIM at the required longword offset */ - memset(&hgp, 0, sizeof(HGP)); - to_slim = (uint8_t *)phba->MBslimaddr + (SLIMOFF*sizeof (uint32_t)); - lpfc_memcpy_to_slim(to_slim, &hgp, sizeof (HGP)); + memset(&hgp, 0, sizeof(struct lpfc_hgp)); + to_slim = phba->MBslimaddr + (SLIMOFF*sizeof (uint32_t)); + + for (i=0; i < phba->sli.num_rings; i++) { + lpfc_memcpy_to_slim(to_slim, &hgp, sizeof(struct lpfc_hgp)); + to_slim += sizeof (struct lpfc_hgp); + } /* Setup Port Group ring pointer */ offset = (uint8_t *)&phba->slim2p->mbx.us.s2.port - @@ -633,15 +604,25 @@ lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) } /* Swap PCB if needed */ - lpfc_sli_pcimem_bcopy((uint32_t *)&phba->slim2p->pcb, - (uint32_t *)&phba->slim2p->pcb, - sizeof (PCB_t)); + lpfc_sli_pcimem_bcopy(&phba->slim2p->pcb, &phba->slim2p->pcb, + sizeof (PCB_t)); lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "%d:0405 Service Level Interface (SLI) 2 selected\n", phba->brd_no); } +void +lpfc_kill_board(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) +{ + MAILBOX_t *mb = &pmb->mb; + + memset(pmb, 0, sizeof(LPFC_MBOXQ_t)); + mb->mbxCommand = MBX_KILL_BOARD; + mb->mbxOwner = OWN_HOST; + return; +} + void lpfc_mbox_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq) { @@ -662,11 +643,27 @@ lpfc_mbox_get(struct lpfc_hba * phba) LPFC_MBOXQ_t *mbq = NULL; struct lpfc_sli *psli = &phba->sli; - if (!list_empty(&psli->mboxq)) { - mbq = list_entry(psli->mboxq.next, LPFC_MBOXQ_t, list); - list_del_init(&mbq->list); + list_remove_head((&psli->mboxq), mbq, LPFC_MBOXQ_t, + list); + if (mbq) { psli->mboxq_cnt--; } return mbq; } + +int +lpfc_mbox_tmo_val(struct lpfc_hba *phba, int cmd) +{ + switch (cmd) { + case MBX_WRITE_NV: /* 0x03 */ + case MBX_UPDATE_CFG: /* 0x1B */ + case MBX_DOWN_LOAD: /* 0x1C */ + case MBX_DEL_LD_ENTRY: /* 0x1D */ + case MBX_LOAD_AREA: /* 0x81 */ + case MBX_FLASH_WR_ULA: /* 0x98 */ + case MBX_LOAD_EXP_ROM: /* 0x9C */ + return LPFC_MBOX_TMO_FLASH_CMD; + } + return LPFC_MBOX_TMO; +}