From owner-svn-src-stable@FreeBSD.ORG Mon Nov 17 23:07:20 2008 Return-Path: Delivered-To: svn-src-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 7801E1065670; Mon, 17 Nov 2008 23:07:19 +0000 (UTC) (envelope-from ambrisko@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 60C788FC0C; Mon, 17 Nov 2008 23:07:19 +0000 (UTC) (envelope-from ambrisko@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id mAHN7JE4060628; Mon, 17 Nov 2008 23:07:19 GMT (envelope-from ambrisko@svn.freebsd.org) Received: (from ambrisko@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id mAHN7J1p060623; Mon, 17 Nov 2008 23:07:19 GMT (envelope-from ambrisko@svn.freebsd.org) Message-Id: <200811172307.mAHN7J1p060623@svn.freebsd.org> From: Doug Ambrisko Date: Mon, 17 Nov 2008 23:07:19 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r185034 - in stable/7/sys: . dev/mfi X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 17 Nov 2008 23:07:20 -0000 Author: ambrisko Date: Mon Nov 17 23:07:18 2008 New Revision: 185034 URL: http://svn.freebsd.org/changeset/base/185034 Log: MFC 182085, 184897, 184933, 184974, 184975 This addresses: 1) New HW support from LSI (they want to get the HW support into a FreeBSD release before the HW comes out!). 2) Bug fix in the ioctl path with zero length command. 3) Adds functional support so that SCSI sense will work when requested from user-land. This is a little strange, since they store a user-land pointer in the "data" space of the ioctl packet. So copy the data out into another structure that is a union of the data and pointer (mfi_sense_ptr union). This way we can cleanly use the pointer, as pointer on both 64bit and 32bit machines (i386/amd64). Submitted by: LSI Approved by: re (kib) Modified: stable/7/sys/ (props changed) stable/7/sys/dev/mfi/mfi.c stable/7/sys/dev/mfi/mfi_ioctl.h stable/7/sys/dev/mfi/mfi_pci.c stable/7/sys/dev/mfi/mfireg.h stable/7/sys/dev/mfi/mfivar.h Modified: stable/7/sys/dev/mfi/mfi.c ============================================================================== --- stable/7/sys/dev/mfi/mfi.c Mon Nov 17 22:46:29 2008 (r185033) +++ stable/7/sys/dev/mfi/mfi.c Mon Nov 17 23:07:18 2008 (r185034) @@ -163,7 +163,11 @@ static void mfi_enable_intr_ppc(struct mfi_softc *sc) { MFI_WRITE4(sc, MFI_ODCR0, 0xFFFFFFFF); - MFI_WRITE4(sc, MFI_OMSK, ~MFI_1078_EIM); + if (sc->mfi_flags & MFI_FLAGS_1078) { + MFI_WRITE4(sc, MFI_OMSK, ~MFI_1078_EIM); + } else if (sc->mfi_flags & MFI_FLAGS_GEN2) { + MFI_WRITE4(sc, MFI_OMSK, ~MFI_GEN2_EIM); + } } static int32_t @@ -171,14 +175,14 @@ mfi_read_fw_status_xscale(struct mfi_sof { return MFI_READ4(sc, MFI_OMSG0); } - + static int32_t mfi_read_fw_status_ppc(struct mfi_softc *sc) { return MFI_READ4(sc, MFI_OSP0); } -static int +static int mfi_check_clear_intr_xscale(struct mfi_softc *sc) { int32_t status; @@ -189,28 +193,35 @@ mfi_check_clear_intr_xscale(struct mfi_s MFI_WRITE4(sc, MFI_OSTS, status); return 0; - } +} -static int +static int mfi_check_clear_intr_ppc(struct mfi_softc *sc) { int32_t status; status = MFI_READ4(sc, MFI_OSTS); - if (!status) - return 1; + if (sc->mfi_flags & MFI_FLAGS_1078) { + if (!(status & MFI_1078_RM)) { + return 1; + } + } else if (sc->mfi_flags & MFI_FLAGS_GEN2) { + if (!(status & MFI_GEN2_RM)) { + return 1; + } + } MFI_WRITE4(sc, MFI_ODCR0, status); return 0; - } +} -static void +static void mfi_issue_cmd_xscale(struct mfi_softc *sc,uint32_t bus_add,uint32_t frame_cnt) { MFI_WRITE4(sc, MFI_IQP,(bus_add >>3)|frame_cnt); } - -static void + +static void mfi_issue_cmd_ppc(struct mfi_softc *sc,uint32_t bus_add,uint32_t frame_cnt) { MFI_WRITE4(sc, MFI_IQP, (bus_add |frame_cnt <<1)|1 ); @@ -1399,6 +1410,8 @@ mfi_bio_complete(struct mfi_command *cm) device_printf(sc->mfi_dev, "I/O error, status= %d " "scsi_status= %d\n", hdr->cmd_status, hdr->scsi_status); mfi_print_sense(cm->cm_sc, cm->cm_sense); + } else if (cm->cm_error != 0) { + bio->bio_flags |= BIO_ERROR; } mfi_release_command(cm); @@ -1815,6 +1828,9 @@ mfi_check_command_post(struct mfi_softc case MFI_DCMD_CFG_ADD: mfi_ldprobe(sc); break; + case MFI_DCMD_CFG_FOREIGN_IMPORT: + mfi_ldprobe(sc); + break; } } @@ -1904,7 +1920,7 @@ mfi_ioctl(struct cdev *dev, u_long cmd, struct mfi_ioc_aen *aen; struct mfi_command *cm = NULL; uint32_t context; - uint8_t *sense_ptr; + union mfi_sense_ptr sense_ptr; uint8_t *data = NULL, *temp; int i; struct mfi_ioc_passthru *iop = (struct mfi_ioc_passthru *)arg; @@ -1986,8 +2002,9 @@ mfi_ioctl(struct cdev *dev, u_long cmd, context = cm->cm_frame->header.context; bcopy(ioc->mfi_frame.raw, cm->cm_frame, - 2 * MFI_DCMD_FRAME_SIZE); /* this isn't quite right */ - cm->cm_total_frame_size = (sizeof(union mfi_sgl) * ioc->mfi_sge_count) + ioc->mfi_sgl_off; + 2 * MFI_DCMD_FRAME_SIZE); /* this isn't quite right */ + cm->cm_total_frame_size = (sizeof(union mfi_sgl) + * ioc->mfi_sge_count) + ioc->mfi_sgl_off; if (ioc->mfi_sge_count) { cm->cm_sg = (union mfi_sgl *)&cm->cm_frame->bytes[ioc->mfi_sgl_off]; @@ -2001,7 +2018,8 @@ mfi_ioctl(struct cdev *dev, u_long cmd, if (cm->cm_flags == 0) cm->cm_flags |= MFI_CMD_DATAIN | MFI_CMD_DATAOUT; cm->cm_len = cm->cm_frame->header.data_len; - if (cm->cm_flags & (MFI_CMD_DATAIN | MFI_CMD_DATAOUT)) { + if (cm->cm_len && + (cm->cm_flags & (MFI_CMD_DATAIN | MFI_CMD_DATAOUT))) { cm->cm_data = data = malloc(cm->cm_len, M_MFIBUF, M_WAITOK | M_ZERO); if (cm->cm_data == NULL) { @@ -2051,6 +2069,11 @@ mfi_ioctl(struct cdev *dev, u_long cmd, if (cm->cm_frame->header.cmd == MFI_CMD_DCMD) locked = mfi_config_lock(sc, cm->cm_frame->dcmd.opcode); + if (cm->cm_frame->header.cmd == MFI_CMD_PD_SCSI_IO) { + cm->cm_frame->pass.sense_addr_lo = cm->cm_sense_busaddr; + cm->cm_frame->pass.sense_addr_hi = 0; + } + mtx_lock(&sc->mfi_io_lock); error = mfi_check_command_pre(sc, cm); if (error) { @@ -2102,10 +2125,20 @@ mfi_ioctl(struct cdev *dev, u_long cmd, } if (ioc->mfi_sense_len) { - /* copy out sense */ - sense_ptr = &((struct mfi_ioc_packet*)arg) - ->mfi_frame.raw[0]; - error = copyout(cm->cm_sense, sense_ptr, + /* get user-space sense ptr then copy out sense */ + bcopy(&((struct mfi_ioc_packet*)arg) + ->mfi_frame.raw[ioc->mfi_sense_off], + &sense_ptr.sense_ptr_data[0], + sizeof(sense_ptr.sense_ptr_data)); +#ifdef __amd64__ + if (cmd != MFI_CMD) { + /* + * not 64bit native so zero out any address + * over 32bit */ + sense_ptr.addr.high = 0; + } +#endif + error = copyout(cm->cm_sense, sense_ptr.user_space, ioc->mfi_sense_len); if (error != 0) { device_printf(sc->mfi_dev, @@ -2207,7 +2240,7 @@ mfi_linux_ioctl_int(struct cdev *dev, u_ struct mfi_linux_ioc_aen l_aen; struct mfi_command *cm = NULL; struct mfi_aen *mfi_aen_entry; - uint8_t *sense_ptr; + union mfi_sense_ptr sense_ptr; uint32_t context; uint8_t *data = NULL, *temp; int i; @@ -2241,7 +2274,8 @@ mfi_linux_ioctl_int(struct cdev *dev, u_ bcopy(l_ioc.lioc_frame.raw, cm->cm_frame, 2 * MFI_DCMD_FRAME_SIZE); /* this isn't quite right */ - cm->cm_total_frame_size = (sizeof(union mfi_sgl) * l_ioc.lioc_sge_count) + l_ioc.lioc_sgl_off; + cm->cm_total_frame_size = (sizeof(union mfi_sgl) + * l_ioc.lioc_sge_count) + l_ioc.lioc_sgl_off; if (l_ioc.lioc_sge_count) cm->cm_sg = (union mfi_sgl *)&cm->cm_frame->bytes[l_ioc.lioc_sgl_off]; @@ -2251,7 +2285,8 @@ mfi_linux_ioctl_int(struct cdev *dev, u_ if (cm->cm_frame->header.flags & MFI_FRAME_DATAOUT) cm->cm_flags |= MFI_CMD_DATAOUT; cm->cm_len = cm->cm_frame->header.data_len; - if (cm->cm_flags & (MFI_CMD_DATAIN | MFI_CMD_DATAOUT)) { + if (cm->cm_len && + (cm->cm_flags & (MFI_CMD_DATAIN | MFI_CMD_DATAOUT))) { cm->cm_data = data = malloc(cm->cm_len, M_MFIBUF, M_WAITOK | M_ZERO); if (cm->cm_data == NULL) { @@ -2283,6 +2318,11 @@ mfi_linux_ioctl_int(struct cdev *dev, u_ if (cm->cm_frame->header.cmd == MFI_CMD_DCMD) locked = mfi_config_lock(sc, cm->cm_frame->dcmd.opcode); + if (cm->cm_frame->header.cmd == MFI_CMD_PD_SCSI_IO) { + cm->cm_frame->pass.sense_addr_lo = cm->cm_sense_busaddr; + cm->cm_frame->pass.sense_addr_hi = 0; + } + mtx_lock(&sc->mfi_io_lock); error = mfi_check_command_pre(sc, cm); if (error) { @@ -2316,10 +2356,19 @@ mfi_linux_ioctl_int(struct cdev *dev, u_ } if (l_ioc.lioc_sense_len) { - /* copy out sense */ - sense_ptr = &((struct mfi_linux_ioc_packet*)arg) - ->lioc_frame.raw[0]; - error = copyout(cm->cm_sense, sense_ptr, + /* get user-space sense ptr then copy out sense */ + bcopy(&((struct mfi_linux_ioc_packet*)arg) + ->lioc_frame.raw[l_ioc.lioc_sense_off], + &sense_ptr.sense_ptr_data[0], + sizeof(sense_ptr.sense_ptr_data)); +#ifdef __amd64__ + /* + * only 32bit Linux support so zero out any + * address over 32bit + */ + sense_ptr.addr.high = 0; +#endif + error = copyout(cm->cm_sense, sense_ptr.user_space, l_ioc.lioc_sense_len); if (error != 0) { device_printf(sc->mfi_dev, Modified: stable/7/sys/dev/mfi/mfi_ioctl.h ============================================================================== --- stable/7/sys/dev/mfi/mfi_ioctl.h Mon Nov 17 22:46:29 2008 (r185033) +++ stable/7/sys/dev/mfi/mfi_ioctl.h Mon Nov 17 23:07:18 2008 (r185034) @@ -50,6 +50,16 @@ union mfi_statrequest { struct mfi_qstat ms_qstat; }; +#define MAX_SPACE_FOR_SENSE_PTR 32 +union mfi_sense_ptr { + uint8_t sense_ptr_data[MAX_SPACE_FOR_SENSE_PTR]; + void *user_space; + struct { + uint32_t low; + uint32_t high; + } addr; +} __packed; + #define MAX_IOCTL_SGE 16 struct mfi_ioc_packet { Modified: stable/7/sys/dev/mfi/mfi_pci.c ============================================================================== --- stable/7/sys/dev/mfi/mfi_pci.c Mon Nov 17 22:46:29 2008 (r185033) +++ stable/7/sys/dev/mfi/mfi_pci.c Mon Nov 17 23:07:18 2008 (r185034) @@ -118,7 +118,14 @@ struct mfi_ident { {0x1000, 0x0413, 0xffff, 0xffff, MFI_FLAGS_1064R, "LSI MegaSAS 1064R"}, /* Verde ZCR */ {0x1028, 0x0015, 0xffff, 0xffff, MFI_FLAGS_1064R, "Dell PERC 5/i"}, {0x1000, 0x0060, 0x1028, 0xffff, MFI_FLAGS_1078, "Dell PERC 6"}, - {0x1000, 0x0060, 0xffff, 0xffff, MFI_FLAGS_1078, "LSI MegaSAS 1078"}, + {0x1000, 0x0060, 0xffff, 0xffff, MFI_FLAGS_1078, "LSI MegaSAS 1078"}, + {0x1000, 0x0079, 0x1028, 0x1f15, MFI_FLAGS_GEN2, "Dell PERC 607E Adapter"}, + {0x1000, 0x0079, 0x1028, 0x1f16, MFI_FLAGS_GEN2, "Dell PERC 607I Adapter"}, + {0x1000, 0x0079, 0x1028, 0x1f17, MFI_FLAGS_GEN2, "Dell PERC 607I Integrated"}, + {0x1000, 0x0079, 0x1028, 0x1f18, MFI_FLAGS_GEN2, "Dell PERC 607I Modular"}, + {0x1000, 0x0078, 0xffff, 0xffff, MFI_FLAGS_GEN2, "LSI MegaSAS Gen2"}, + {0x1000, 0x0079, 0xffff, 0xffff, MFI_FLAGS_GEN2, "LSI MegaSAS Gen2"}, + {0x1000, 0x007c, 0xffff, 0xffff, MFI_FLAGS_1078, "LSI MegaSAS 1078"}, {0, 0, 0, 0, 0, NULL} }; @@ -163,6 +170,8 @@ mfi_pci_attach(device_t dev) sc = device_get_softc(dev); bzero(sc, sizeof(*sc)); sc->mfi_dev = dev; + m = mfi_find_ident(dev); + sc->mfi_flags = m->flags; /* Verify that the adapter can be set up in PCI space */ command = pci_read_config(dev, PCIR_COMMAND, 2); @@ -179,7 +188,14 @@ mfi_pci_attach(device_t dev) } /* Allocate PCI registers */ - sc->mfi_regs_rid = PCIR_BAR(0); + if ((sc->mfi_flags & MFI_FLAGS_1064R) || + (sc->mfi_flags & MFI_FLAGS_1078)) { + /* 1068/1078: Memory mapped BAR is at offset 0x10 */ + sc->mfi_regs_rid = PCIR_BAR(0); + } else if (sc->mfi_flags & MFI_FLAGS_GEN2) { + /* GEN2: Memory mapped BAR is at offset 0x14 */ + sc->mfi_regs_rid = PCIR_BAR(1); + } if ((sc->mfi_regs_resource = bus_alloc_resource_any(sc->mfi_dev, SYS_RES_MEMORY, &sc->mfi_regs_rid, RF_ACTIVE)) == NULL) { device_printf(dev, "Cannot allocate PCI registers\n"); @@ -206,9 +222,6 @@ mfi_pci_attach(device_t dev) goto out; } - m = mfi_find_ident(dev); - sc->mfi_flags = m->flags; - error = mfi_attach(sc); out: if (error) { Modified: stable/7/sys/dev/mfi/mfireg.h ============================================================================== --- stable/7/sys/dev/mfi/mfireg.h Mon Nov 17 22:46:29 2008 (r185033) +++ stable/7/sys/dev/mfi/mfireg.h Mon Nov 17 23:07:18 2008 (r185034) @@ -89,10 +89,16 @@ __FBSDID("$FreeBSD$"); #define MFI_ODCR0 0xa0 /* outbound doorbell clear register0 */ #define MFI_OSP0 0xb0 /* outbound scratch pad0 */ #define MFI_1078_EIM 0x80000004 /* 1078 enable intrrupt mask */ -#define MFI_RMI 0x2 /* reply message interrupt */ +#define MFI_RMI 0x2 /* reply message interrupt */ #define MFI_1078_RM 0x80000000 /* reply 1078 message interrupt */ #define MFI_ODC 0x4 /* outbound doorbell change interrupt */ +/* + * GEN2 specific changes + */ +#define MFI_GEN2_EIM 0x00000005 /* GEN2 enable interrupt mask */ +#define MFI_GEN2_RM 0x00000001 /* reply GEN2 message interrupt */ + /* Bits for MFI_OSTS */ #define MFI_OSTS_INTR_VALID 0x00000002 @@ -153,6 +159,7 @@ typedef enum { MFI_DCMD_CFG_READ = 0x04010000, MFI_DCMD_CFG_ADD = 0x04020000, MFI_DCMD_CFG_CLEAR = 0x04030000, + MFI_DCMD_CFG_FOREIGN_IMPORT = 0x04060400, MFI_DCMD_CLUSTER = 0x08000000, MFI_DCMD_CLUSTER_RESET_ALL = 0x08010100, MFI_DCMD_CLUSTER_RESET_LD = 0x08010200 Modified: stable/7/sys/dev/mfi/mfivar.h ============================================================================== --- stable/7/sys/dev/mfi/mfivar.h Mon Nov 17 22:46:29 2008 (r185033) +++ stable/7/sys/dev/mfi/mfivar.h Mon Nov 17 23:07:18 2008 (r185034) @@ -133,6 +133,7 @@ struct mfi_softc { #define MFI_FLAGS_STOP (1<<3) #define MFI_FLAGS_1064R (1<<4) #define MFI_FLAGS_1078 (1<<5) +#define MFI_FLAGS_GEN2 (1<<6) struct mfi_hwcomms *mfi_comms; TAILQ_HEAD(,mfi_command) mfi_free;