Re: [PATCH V6 0/4] [SCSI] ufs: Adds glue drivers to ufshcd
Hi James, look like these patches are fine. Can you please integrate these patches in your tree. On Tue, Feb 5, 2013 at 10:17 PM, wrote: > From: Vinayak Holikatti > > This patch set adds following features > - Seggregate PCI specific code in ufshcd.c and corrected copyright > - Adds PCI glue driver ufshcd-pci.c and ufshcd.c become core module > - Adds Platform glue driver ufshcd-pltfrm.c > - Update correct transfer size in Command UPIU > > Vinayak Holikatti (4): > [SCSI] drivers/scsi/ufs: Seggregate PCI Specific Code > [SCSI] drivers/scsi/ufs: Separate PCI code into glue driver > [SCSI] ufs: Add Platform glue driver for ufshcd > [SCSI] ufs: Correct the expected data transfersize > > drivers/scsi/ufs/Kconfig | 87 +--- > drivers/scsi/ufs/Makefile|2 + > drivers/scsi/ufs/ufs.h | 44 ++--- > drivers/scsi/ufs/ufshcd-pci.c| 211 +++ > drivers/scsi/ufs/ufshcd-pltfrm.c | 217 +++ > drivers/scsi/ufs/ufshcd.c| 426 > -- > drivers/scsi/ufs/ufshcd.h| 202 ++ > drivers/scsi/ufs/ufshci.h| 44 ++--- > 8 files changed, 811 insertions(+), 422 deletions(-) > create mode 100644 drivers/scsi/ufs/ufshcd-pci.c > create mode 100644 drivers/scsi/ufs/ufshcd-pltfrm.c > create mode 100644 drivers/scsi/ufs/ufshcd.h > > -- > 1.7.5.4 > -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [scsi:misc 61/65] drivers/scsi/fnic/fnic_scsi.c:441:3: warning: cast from pointer to integer of different size
Hi James, I have fixed fnic patches 3-10 for sparse and smatch errors. Thanks, Hiral On 1/29/13 10:26 PM, "kbuild test robot" wrote: >tree: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git misc >head: 52cb5cbe9b8ed89db0f8c9eeec8410fcfb0887fd >commit: 6f3b5679f2af1ef3becbf7832d2bce977907c08a [61/65] [SCSI] fnic: >fixing issues in device and firmware reset code >config: make ARCH=i386 allmodconfig > >All warnings: > > drivers/scsi/fnic/fnic_scsi.c:190:39: sparse: context imbalance in >'__fnic_set_state_flags' - unexpected unlock > drivers/scsi/fnic/fnic_scsi.c:419:19: sparse: context imbalance in >'fnic_queuecommand_lck' - unexpected unlock > drivers/scsi/fnic/fnic_scsi.c:2411:49: sparse: context imbalance in >'fnic_is_abts_pending' - different lock contexts for basic block > drivers/scsi/fnic/fnic_scsi.c: In function 'fnic_queuecommand_lck': >>> drivers/scsi/fnic/fnic_scsi.c:441:3: warning: cast from pointer to >>>integer of different size [-Wpointer-to-int-cast] >>> drivers/scsi/fnic/fnic_scsi.c:441:3: warning: cast from pointer to >>>integer of different size [-Wpointer-to-int-cast] >>> drivers/scsi/fnic/fnic_scsi.c:493:3: warning: cast from pointer to >>>integer of different size [-Wpointer-to-int-cast] >>> drivers/scsi/fnic/fnic_scsi.c:493:3: warning: cast from pointer to >>>integer of different size [-Wpointer-to-int-cast] >>> drivers/scsi/fnic/fnic_scsi.c:515:2: warning: cast from pointer to >>>integer of different size [-Wpointer-to-int-cast] >>> drivers/scsi/fnic/fnic_scsi.c:515:2: warning: cast from pointer to >>>integer of different size [-Wpointer-to-int-cast] >>> drivers/scsi/fnic/fnic_scsi.c:515:2: warning: cast from pointer to >>>integer of different size [-Wpointer-to-int-cast] > drivers/scsi/fnic/fnic_scsi.c: In function 'fnic_fcpio_ack_handler': >>> drivers/scsi/fnic/fnic_scsi.c:703:2: warning: cast from pointer to >>>integer of different size [-Wpointer-to-int-cast] > drivers/scsi/fnic/fnic_scsi.c: In function >'fnic_fcpio_icmnd_cmpl_handler': >>> drivers/scsi/fnic/fnic_scsi.c:747:3: warning: cast from pointer to >>>integer of different size [-Wpointer-to-int-cast] >>> drivers/scsi/fnic/fnic_scsi.c:747:3: warning: cast from pointer to >>>integer of different size [-Wpointer-to-int-cast] >>> drivers/scsi/fnic/fnic_scsi.c:904:2: warning: cast from pointer to >>>integer of different size [-Wpointer-to-int-cast] >>> drivers/scsi/fnic/fnic_scsi.c:904:2: warning: cast from pointer to >>>integer of different size [-Wpointer-to-int-cast] >>> drivers/scsi/fnic/fnic_scsi.c:904:2: warning: cast from pointer to >>>integer of different size [-Wpointer-to-int-cast] > drivers/scsi/fnic/fnic_scsi.c: In function >'fnic_fcpio_itmf_cmpl_handler': >>> drivers/scsi/fnic/fnic_scsi.c:1022:5: warning: cast from pointer to >>>integer of different size [-Wpointer-to-int-cast] >>> drivers/scsi/fnic/fnic_scsi.c:1022:5: warning: cast from pointer to >>>integer of different size [-Wpointer-to-int-cast] >>> drivers/scsi/fnic/fnic_scsi.c:1022:5: warning: cast from pointer to >>>integer of different size [-Wpointer-to-int-cast] >>> drivers/scsi/fnic/fnic_scsi.c:1044:4: warning: cast from pointer to >>>integer of different size [-Wpointer-to-int-cast] >>> drivers/scsi/fnic/fnic_scsi.c:1044:4: warning: cast from pointer to >>>integer of different size [-Wpointer-to-int-cast] >>> drivers/scsi/fnic/fnic_scsi.c:1044:4: warning: cast from pointer to >>>integer of different size [-Wpointer-to-int-cast] >>> drivers/scsi/fnic/fnic_scsi.c:1059:4: warning: cast from pointer to >>>integer of different size [-Wpointer-to-int-cast] >-- > drivers/scsi/fnic/fnic_trace.c: In function 'fnic_trace_get_buf': >>> drivers/scsi/fnic/fnic_trace.c:80:9: warning: cast to pointer from >>>integer of different size [-Wint-to-pointer-cast] > drivers/scsi/fnic/fnic_trace.c: In function 'fnic_get_trace_data': >>> drivers/scsi/fnic/fnic_trace.c:112:10: warning: cast to pointer from >>>integer of different size [-Wint-to-pointer-cast] >>> drivers/scsi/fnic/fnic_trace.c:149:10: warning: cast to pointer from >>>integer of different size [-Wint-to-pointer-cast] > drivers/scsi/fnic/fnic_trace.c: In function 'fnic_trace_buf_init': >>> drivers/scsi/fnic/fnic_trace.c:200:21: warning: cast from pointer to >>>integer of different size [-Wpointer-to-int-cast] >>> drivers/scsi/fnic/fnic_trace.c:207:2: warning: cast to pointer from >>>integer of different size [-Wint-to-pointer-cast] >>> drivers/scsi/fnic/fnic_trace.c:215:10: warning: cast to pointer from >>>integer of different size [-Wint-to-pointer-cast] > drivers/scsi/fnic/fnic_trace.c: In function 'fnic_trace_free': >>> drivers/scsi/fnic/fnic_trace.c:260:9: warning: cast to pointer from >>>integer of different size [-Wint-to-pointer-cast] > >sparse warnings: (new ones prefixed by >>) > >>> drivers/scsi/fnic/fnic_scsi.c:190:39: sparse: context imbalance in >>>'__fnic_set_state_flags' - unexpected unlock > drivers/scsi/fnic/fnic_scsi.c:419:19: sparse: context imbalance i
[PATCH 07/10] fnic: Fnic Trace Utility
Fnic Trace utility is a tracing functionality built directly into fnic driver to trace events. The benefit that trace buffer brings to fnic driver is the ability to see what it happening inside the fnic driver. It also provides the capability to trace every IO event inside fnic driver to debug panics, hangs and potentially IO corruption issues. This feature makes it easy to find problems in fnic driver and it also helps in tracking down strange bugs in a more manageable way. Trace buffer is shared across all fnic instances for this implementation. Signed-off-by: Hiral Patel --- drivers/scsi/fnic/Makefile |2 + drivers/scsi/fnic/fnic.h |1 + drivers/scsi/fnic/fnic_debugfs.c | 314 ++ drivers/scsi/fnic/fnic_main.c| 14 ++ drivers/scsi/fnic/fnic_scsi.c| 120 +-- drivers/scsi/fnic/fnic_trace.c | 273 + drivers/scsi/fnic/fnic_trace.h | 90 +++ 7 files changed, 803 insertions(+), 11 deletions(-) create mode 100644 drivers/scsi/fnic/fnic_debugfs.c create mode 100644 drivers/scsi/fnic/fnic_trace.c create mode 100644 drivers/scsi/fnic/fnic_trace.h diff --git a/drivers/scsi/fnic/Makefile b/drivers/scsi/fnic/Makefile index 37c3440..383598f 100644 --- a/drivers/scsi/fnic/Makefile +++ b/drivers/scsi/fnic/Makefile @@ -7,6 +7,8 @@ fnic-y := \ fnic_res.o \ fnic_fcs.o \ fnic_scsi.o \ + fnic_trace.o \ + fnic_debugfs.o \ vnic_cq.o \ vnic_dev.o \ vnic_intr.o \ diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h index 9c95a1a..98436c3 100644 --- a/drivers/scsi/fnic/fnic.h +++ b/drivers/scsi/fnic/fnic.h @@ -26,6 +26,7 @@ #include #include "fnic_io.h" #include "fnic_res.h" +#include "fnic_trace.h" #include "vnic_dev.h" #include "vnic_wq.h" #include "vnic_rq.h" diff --git a/drivers/scsi/fnic/fnic_debugfs.c b/drivers/scsi/fnic/fnic_debugfs.c new file mode 100644 index 000..adc1f7f --- /dev/null +++ b/drivers/scsi/fnic/fnic_debugfs.c @@ -0,0 +1,314 @@ +/* + * Copyright 2012 Cisco Systems, Inc. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include "fnic.h" + +static struct dentry *fnic_trace_debugfs_root; +static struct dentry *fnic_trace_debugfs_file; +static struct dentry *fnic_trace_enable; + +/* + * fnic_trace_ctrl_open - Open the trace_enable file + * @inode: The inode pointer. + * @file: The file pointer to attach the trace enable/disable flag. + * + * Description: + * This routine opens a debugsfs file trace_enable. + * + * Returns: + * This function returns zero if successful. + */ +static int fnic_trace_ctrl_open(struct inode *inode, struct file *filp) +{ + filp->private_data = inode->i_private; + return 0; +} + +/* + * fnic_trace_ctrl_read - Read a trace_enable debugfs file + * @filp: The file pointer to read from. + * @ubuf: The buffer to copy the data to. + * @cnt: The number of bytes to read. + * @ppos: The position in the file to start reading from. + * + * Description: + * This routine reads value of variable fnic_tracing_enabled + * and stores into local @buf. It will start reading file at @ppos and + * copy up to @cnt of data to @ubuf from @buf. + * + * Returns: + * This function returns the amount of data that was read. + */ +static ssize_t fnic_trace_ctrl_read(struct file *filp, + char __user *ubuf, + size_t cnt, loff_t *ppos) +{ + char buf[64]; + int len; + len = sprintf(buf, "%u\n", fnic_tracing_enabled); + + return simple_read_from_buffer(ubuf, cnt, ppos, buf, len); +} + +/* + * fnic_trace_ctrl_write - Write to trace_enable debugfs file + * @filp: The file pointer to write from. + * @ubuf: The buffer to copy the data from. + * @cnt: The number of bytes to write. + * @ppos: The position in the file to start writing to. + * + * Description: + * This routine writes data from user buffer @ubuf to buffer @buf and + * sets fnic_tracing_enabled value as per user input. + * + * Returns: + * This function returns the amount of data that was written. + */ +static ssize_t fnic_trace_ctrl_write(struct file *filp, + const char __user *ubuf, +
[PATCH 08/10] fnic: FIP VLAN Discovery Feature Support
FIP VLAN discovery discovers the FCoE VLAN that will be used by all other FIP protocols as well as by the FCoE encapsulation for Fibre Channel payloads on the established virtual link. One of the goals of FC-BB-5 was to be as nonintrusive as possible on initiators and targets, and therefore FIP VLAN discovery occurs in the native VLAN used by the initiator or target to exchange Ethernet traffic. The FIP VLAN discovery protocol is the only FIP protocol running on the native VLAN; all other FIP protocols run on the discovered FCoE VLANs. If an administrator has manually configured FCoE VLANs on ENodes and FCFs, there is no need to use this protocol. FIP and FCoE will run over the configured VLANs. An ENode without FCoE VLANs configuration would use this automated discovery protocol to discover over which VLANs FCoE is running. The ENode sends a FIP VLAN discovery request to a multicast MAC address called All-FCF-MACs, which is a multicast MAC address to which all FCFs listen. All FCFs that can be reached in the native VLAN of the ENode are expected to respond on the same VLAN with a response that lists one or more FCoE VLANs that are available for the ENode's VN_Port login. This protocol has the sole purpose of allowing the ENode to discover all the available FCoE VLANs. Now the ENode may enable a subset of these VLANs for FCoE Running the FIP protocol in these VLANs on a per VLAN basis. And FCoE data transactions also would occur on this VLAN. Hence, Except for FIP VLAN discovery, all other FIP and FCoE traffic runs on the selected FCoE VLAN. Its only the FIP VLAN Discovery protocol that is permitted to run on the Default native VLAN of the system. [ NOTE ] We are working on moving this feature definitions and functionality to libfcoe module. We need this patch to be approved, as Suse is looking forward to merge this feature in SLES 11 SP3 release. Once this patch is approved, we will submit patch which should move vlan discovery feature to libfoce. Signed-off-by: Anantha Prakash T Signed-off-by: Hiral Patel --- drivers/scsi/fnic/fnic.h| 32 +++ drivers/scsi/fnic/fnic_fcs.c| 558 ++- drivers/scsi/fnic/fnic_fip.h| 68 + drivers/scsi/fnic/fnic_main.c | 51 +++- drivers/scsi/fnic/vnic_dev.c| 10 + drivers/scsi/fnic/vnic_dev.h|2 + drivers/scsi/fnic/vnic_devcmd.h | 67 + 7 files changed, 784 insertions(+), 4 deletions(-) create mode 100644 drivers/scsi/fnic/fnic_fip.h diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h index 98436c3..acec42a 100644 --- a/drivers/scsi/fnic/fnic.h +++ b/drivers/scsi/fnic/fnic.h @@ -192,6 +192,18 @@ enum fnic_state { struct mempool; +enum fnic_evt { + FNIC_EVT_START_VLAN_DISC = 1, + FNIC_EVT_START_FCF_DISC = 2, + FNIC_EVT_MAX, +}; + +struct fnic_event { + struct list_head list; + struct fnic *fnic; + enum fnic_evt event; +}; + /* Per-instance private data structure */ struct fnic { struct fc_lport *lport; @@ -254,6 +266,18 @@ struct fnic { struct sk_buff_head frame_queue; struct sk_buff_head tx_queue; + /*** FIP related data members -- start ***/ + void (*set_vlan)(struct fnic *, u16 vlan); + struct work_struct fip_frame_work; + struct sk_buff_head fip_frame_queue; + struct timer_list fip_timer; + struct list_headvlans; + spinlock_t vlans_lock; + + struct work_struct event_work; + struct list_headevlist; + /*** FIP related data members -- end ***/ + /* copy work queue cache line section */ cacheline_aligned struct vnic_wq_copy wq_copy[FNIC_WQ_COPY_MAX]; /* completion queue cache line section */ @@ -278,6 +302,7 @@ static inline struct fnic *fnic_from_ctlr(struct fcoe_ctlr *fip) } extern struct workqueue_struct *fnic_event_queue; +extern struct workqueue_struct *fnic_fip_queue; extern struct device_attribute *fnic_attrs[]; void fnic_clear_intr_mode(struct fnic *fnic); @@ -289,6 +314,7 @@ int fnic_send(struct fc_lport *, struct fc_frame *); void fnic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf); void fnic_handle_frame(struct work_struct *work); void fnic_handle_link(struct work_struct *work); +void fnic_handle_event(struct work_struct *work); int fnic_rq_cmpl_handler(struct fnic *fnic, int); int fnic_alloc_rq_frame(struct vnic_rq *rq); void fnic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf); @@ -321,6 +347,12 @@ void fnic_handle_link_event(struct fnic *fnic); int fnic_is_abts_pending(struct fnic *, struct scsi_cmnd *); +void fnic_handle_fip_frame(struct work_struct *work); +void fnic_handle_fip_event(struct fnic *fnic); +void fnic_fcoe_reset_vlans(struct fnic *fnic); +void fnic_fcoe_evlist_free(struct fnic *fnic); +extern void fnic_handle_fip_timer(struct fnic *fnic); + static inline int fnic_chk_sta
[PATCH 10/10] fnic: Incremented driver version
Incrementing driver versio after bug fixes and new feature commits. Signed-off-by: Brian Uchino Signed-off-by: Hiral Patel --- drivers/scsi/fnic/fnic.h |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h index acec42a..b6d1f92 100644 --- a/drivers/scsi/fnic/fnic.h +++ b/drivers/scsi/fnic/fnic.h @@ -38,7 +38,7 @@ #define DRV_NAME "fnic" #define DRV_DESCRIPTION"Cisco FCoE HBA Driver" -#define DRV_VERSION"1.5.0.2" +#define DRV_VERSION"1.5.0.22" #define PFXDRV_NAME ": " #define DFX DRV_NAME "%d: " -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 09/10] fnic: Kernel panic due to FIP mode misconfiguration
If switch configured in FIP and adapter configured in non-fip mode, driver panics while queueing FIP frame in non-existing fip_frame_queue. Added config check before queueing FIP frame in misconfiguration case to avoid kernel panic. Signed-off-by: Hiral Patel --- drivers/scsi/fnic/fnic_fcs.c |6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/scsi/fnic/fnic_fcs.c b/drivers/scsi/fnic/fnic_fcs.c index 41faca4..a0092e8 100644 --- a/drivers/scsi/fnic/fnic_fcs.c +++ b/drivers/scsi/fnic/fnic_fcs.c @@ -603,6 +603,12 @@ static inline int fnic_import_rq_eth_pkt(struct fnic *fnic, struct sk_buff *skb) skb_reset_mac_header(skb); } if (eh->h_proto == htons(ETH_P_FIP)) { + if (!(fnic->config.flags & VFCF_FIP_CAPABLE)) { + printk(KERN_ERR "Dropped FIP frame, as firmware " + "uses non-FIP mode, Enable FIP " + "using UCSM\n"); + goto drop; + } skb_queue_tail(&fnic->fip_frame_queue, skb); queue_work(fnic_fip_queue, &fnic->fip_frame_work); return 1; /* let caller know packet was used */ -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 06/10] fnic: New debug flags and debug log messages
Added new fnic debug flags for identifying IO state at every stage of IO while debugging and also added more log messages for better debugging capability. Signed-off-by: Sesidhar Baddela Signed-off-by: Hiral Patel --- drivers/scsi/fnic/fnic.h | 31 --- drivers/scsi/fnic/fnic_io.h |4 +- drivers/scsi/fnic/fnic_scsi.c | 118 - 3 files changed, 132 insertions(+), 21 deletions(-) diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h index b8e6644..9c95a1a 100644 --- a/drivers/scsi/fnic/fnic.h +++ b/drivers/scsi/fnic/fnic.h @@ -59,14 +59,29 @@ * Command flags to identify the type of command and for other future * use. */ -#define FNIC_NO_FLAGS 0 -#define FNIC_CDB_REQ BIT(1) /* All IOs with a valid CDB */ -#define FNIC_BLOCKING_REQ BIT(2) /* All blocking Requests */ -#define FNIC_DEVICE_RESET BIT(3) /* Device reset request */ -#define FNIC_DEV_RST_PENDING BIT(4) /* Device reset pending */ -#define FNIC_DEV_RST_TIMED_OUT BIT(5) /* Device reset timed out */ -#define FNIC_DEV_RST_TERM_ISSUED BIT(6) /* Device reset terminate */ -#define FNIC_DEV_RST_DONE BIT(7) /* Device reset done */ +#define FNIC_NO_FLAGS 0 +#define FNIC_IO_INITIALIZED BIT(0) +#define FNIC_IO_ISSUED BIT(1) +#define FNIC_IO_DONEBIT(2) +#define FNIC_IO_REQ_NULLBIT(3) +#define FNIC_IO_ABTS_PENDINGBIT(4) +#define FNIC_IO_ABORTED BIT(5) +#define FNIC_IO_ABTS_ISSUED BIT(6) +#define FNIC_IO_TERM_ISSUED BIT(7) +#define FNIC_IO_INTERNAL_TERM_ISSUEDBIT(8) +#define FNIC_IO_ABT_TERM_DONE BIT(9) +#define FNIC_IO_ABT_TERM_REQ_NULL BIT(10) +#define FNIC_IO_ABT_TERM_TIMED_OUT BIT(11) +#define FNIC_DEVICE_RESET BIT(12) /* Device reset request */ +#define FNIC_DEV_RST_ISSUED BIT(13) +#define FNIC_DEV_RST_TIMED_OUT BIT(14) +#define FNIC_DEV_RST_ABTS_ISSUEDBIT(15) +#define FNIC_DEV_RST_TERM_ISSUEDBIT(16) +#define FNIC_DEV_RST_DONE BIT(17) +#define FNIC_DEV_RST_REQ_NULL BIT(18) +#define FNIC_DEV_RST_ABTS_DONE BIT(19) +#define FNIC_DEV_RST_TERM_DONE BIT(20) +#define FNIC_DEV_RST_ABTS_PENDING BIT(21) /* * Usage of the scsi_cmnd scratchpad. diff --git a/drivers/scsi/fnic/fnic_io.h b/drivers/scsi/fnic/fnic_io.h index 3455c34..c35b8f1 100644 --- a/drivers/scsi/fnic/fnic_io.h +++ b/drivers/scsi/fnic/fnic_io.h @@ -45,7 +45,8 @@ enum fnic_sgl_list_type { }; enum fnic_ioreq_state { - FNIC_IOREQ_CMD_PENDING = 0, + FNIC_IOREQ_NOT_INITED = 0, + FNIC_IOREQ_CMD_PENDING, FNIC_IOREQ_ABTS_PENDING, FNIC_IOREQ_ABTS_COMPLETE, FNIC_IOREQ_CMD_COMPLETE, @@ -60,6 +61,7 @@ struct fnic_io_req { u8 sgl_type; /* device DMA descriptor list type */ u8 io_completed:1; /* set to 1 when fw completes IO */ u32 port_id; /* remote port DID */ + unsigned long start_time; /* in jiffies */ struct completion *abts_done; /* completion for abts */ struct completion *dr_done; /* completion for device reset */ }; diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index 6483081..7cb65330 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c @@ -47,6 +47,7 @@ const char *fnic_state_str[] = { }; static const char *fnic_ioreq_state_str[] = { + [FNIC_IOREQ_NOT_INITED] = "FNIC_IOREQ_NOT_INITED", [FNIC_IOREQ_CMD_PENDING] = "FNIC_IOREQ_CMD_PENDING", [FNIC_IOREQ_ABTS_PENDING] = "FNIC_IOREQ_ABTS_PENDING", [FNIC_IOREQ_ABTS_COMPLETE] = "FNIC_IOREQ_ABTS_COMPLETE", @@ -349,6 +350,8 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic, if (unlikely(!vnic_wq_copy_desc_avail(wq))) { spin_unlock_irqrestore(&fnic->wq_copy_lock[0], intr_flags); + FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, + "fnic_queue_wq_copy_desc failure - no descriptors\n"); return SCSI_MLQUEUE_HOST_BUSY; } @@ -420,7 +423,8 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_ * caller disabling them. */ spin_unlock(lp->host->host_lock); - CMD_FLAGS(sc) = FNIC_CDB_REQ; + CMD_STATE(sc) = FNIC_IOREQ_NOT_INITED; + CMD_FLAGS(sc) = FNIC_NO_FLAGS; /* Get a new io_req for this SCSI IO */ io_req = mempool_alloc(fnic->io_req_pool, GFP_ATOMIC); @@ -467,8 +471,10 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_ /* initialize rest of io_req */ io_req->port_id = rport->port_id; + io_req->start_time = jiffies; CMD_STATE(sc) = FNIC_IOREQ_CMD_PENDING; CMD_SP(sc) = (char *)io_req; + CMD_F
[PATCH 05/10] fnic: fnic driver may hit BUG_ON on device reset
The issue was observed when LUN Reset is issued through IOCTL or sg_reset utility. fnic driver issues LUN RESET to firmware. On successful completion of device reset, driver cleans up all the pending IOs that were issued prior to device reset. These pending IOs are expected to be in ABTS_PENDING state. This works fine, when the device reset operation resulted from midlayer, but not when device reset was triggered from IOCTL path as the pending IOs were not in ABTS_PENDING state. execution path hits panic if the pending IO is not in ABTS_PENDING state. Changes: The fix replaces BUG_ON check in fnic_clean_pending_aborts() with marking pending IOs as ABTS_PENDING if they were not in ABTS_PENDING state and skips if they were already in ABTS_PENDING state. An extra check is added to validate the abort status of the commands after a delay of 2 * E_D_TOV using a helper function. The helper function returns 1 if it finds any pending IO in ABTS_PENDING state, belong to the LUN on which device reset was issued else 0. With this, device reset operation returns success only if the helper funciton returns 0, otherwise it returns failure. Other changes: - Removed code in fnic_clean_pending_aborts() that returns failure if it finds io_req NULL, instead of returning failure added code to continue with next io - Added device reset flags for debugging in fnic_terminate_rport_io, fnic_rport_exch_reset, and fnic_clean_pending_aborts Signed-off-by: Narsimhulu Musini Signed-off-by: Hiral Patel --- drivers/scsi/fnic/fnic.h |2 + drivers/scsi/fnic/fnic_scsi.c | 121 ++--- 2 files changed, 116 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h index 63b35c8..b8e6644 100644 --- a/drivers/scsi/fnic/fnic.h +++ b/drivers/scsi/fnic/fnic.h @@ -303,6 +303,8 @@ const char *fnic_state_to_str(unsigned int state); void fnic_log_q_error(struct fnic *fnic); void fnic_handle_link_event(struct fnic *fnic); +int fnic_is_abts_pending(struct fnic *, struct scsi_cmnd *); + static inline int fnic_chk_state_flags_locked(struct fnic *fnic, unsigned long st_flags) { diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index 2f46509..6483081 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c @@ -1271,7 +1271,8 @@ static void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id) spin_unlock_irqrestore(io_lock, flags); } else { spin_lock_irqsave(io_lock, flags); - CMD_FLAGS(sc) |= FNIC_DEV_RST_TERM_ISSUED; + if (CMD_FLAGS(sc) & FNIC_DEVICE_RESET) + CMD_FLAGS(sc) |= FNIC_DEV_RST_TERM_ISSUED; spin_unlock_irqrestore(io_lock, flags); } } @@ -1379,7 +1380,8 @@ void fnic_terminate_rport_io(struct fc_rport *rport) spin_unlock_irqrestore(io_lock, flags); } else { spin_lock_irqsave(io_lock, flags); - CMD_FLAGS(sc) |= FNIC_DEV_RST_TERM_ISSUED; + if (CMD_FLAGS(sc) & FNIC_DEVICE_RESET) + CMD_FLAGS(sc) |= FNIC_DEV_RST_TERM_ISSUED; spin_unlock_irqrestore(io_lock, flags); } } @@ -1592,7 +1594,7 @@ lr_io_req_end: static int fnic_clean_pending_aborts(struct fnic *fnic, struct scsi_cmnd *lr_sc) { - int tag; + int tag, abt_tag; struct fnic_io_req *io_req; spinlock_t *io_lock; unsigned long flags; @@ -1601,6 +1603,7 @@ static int fnic_clean_pending_aborts(struct fnic *fnic, struct scsi_lun fc_lun; struct scsi_device *lun_dev = lr_sc->device; DECLARE_COMPLETION_ONSTACK(tm_done); + enum fnic_ioreq_state old_ioreq_state; for (tag = 0; tag < FNIC_MAX_IO_REQ; tag++) { sc = scsi_host_find_tag(fnic->lport->host, tag); @@ -1629,7 +1632,41 @@ static int fnic_clean_pending_aborts(struct fnic *fnic, "Found IO in %s on lun\n", fnic_ioreq_state_to_str(CMD_STATE(sc))); - BUG_ON(CMD_STATE(sc) != FNIC_IOREQ_ABTS_PENDING); + if (CMD_STATE(sc) == FNIC_IOREQ_ABTS_PENDING) { + spin_unlock_irqrestore(io_lock, flags); + continue; + } + if ((CMD_FLAGS(sc) & FNIC_DEVICE_RESET) && + (!(CMD_FLAGS(sc) & FNIC_DEV_RST_PENDING))) { + FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, + "%s dev rst not pending sc 0x%p\n", __func__, + sc); + spin_unlock_irqrestore(io_lock, flags); + continue; + } + old_ioreq_state = CMD_STATE(sc); +
[PATCH 03/10] fnic:fixing issues in device and firmware reset code
1. Handling overlapped firmware resets This fix serialize multiple firmware resets to avoid situation where fnic device fails to come up for link up event, when firmware resets are issued back to back. If there are overlapped firmware resets are issued, the firmware reset operation checks whether there is any firmware reset in progress, if so it polls for its completion in a loop with 100ms delay. 2. Handling device reset timeout fnic_device_reset code has been modified to handle Device reset timeout: - Issue terminate on device reset timeout. - Introduced flags field (one of the scratch fields in scsi_cmnd). With this, device reset request would have DEVICE_RESET flag set for other routines to determine the type of the request. Also modified fnic_terminate_rport_io, fnic_rport_exch_rset, completion routines to handle SCSI commands with DEVICE_RESET flag. 3. LUN/Device Reset hangs when issued through IOCTL using utilities like sg_reset. Each SCSI command is associated with a valid tag, fnic uses this tag to retrieve associated scsi command on completion. the LUN/Device Reset issued through IOCTL resulting into a SCSI command that is not associated with a valid tag. So fnic fails to retrieve associated scsi command on completion, which causes hang. This fix allocates tag, associates it with the scsi command and frees the tag, when the operation completed. 4. Preventing IOs during firmware reset. Current fnic implementation allows IO submissions during firmware reset. This fix synchronizes IO submissions and firmware reset operations. It ensures that IOs issued to fnic prior to reset will be issued to the firmware before firmware reset. Signed-off-by: Narsimhulu Musini Signed-off-by: Hiral Patel --- drivers/scsi/fnic/fnic.h | 42 + drivers/scsi/fnic/fnic_main.c |3 + drivers/scsi/fnic/fnic_scsi.c | 384 + 3 files changed, 397 insertions(+), 32 deletions(-) diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h index 95a5ba2..63b35c8 100644 --- a/drivers/scsi/fnic/fnic.h +++ b/drivers/scsi/fnic/fnic.h @@ -56,6 +56,19 @@ #define FNIC_NO_TAG -1 /* + * Command flags to identify the type of command and for other future + * use. + */ +#define FNIC_NO_FLAGS 0 +#define FNIC_CDB_REQ BIT(1) /* All IOs with a valid CDB */ +#define FNIC_BLOCKING_REQ BIT(2) /* All blocking Requests */ +#define FNIC_DEVICE_RESET BIT(3) /* Device reset request */ +#define FNIC_DEV_RST_PENDING BIT(4) /* Device reset pending */ +#define FNIC_DEV_RST_TIMED_OUT BIT(5) /* Device reset timed out */ +#define FNIC_DEV_RST_TERM_ISSUED BIT(6) /* Device reset terminate */ +#define FNIC_DEV_RST_DONE BIT(7) /* Device reset done */ + +/* * Usage of the scsi_cmnd scratchpad. * These fields are locked by the hashed io_req_lock. */ @@ -64,6 +77,7 @@ #define CMD_ABTS_STATUS(Cmnd) ((Cmnd)->SCp.Message) #define CMD_LR_STATUS(Cmnd)((Cmnd)->SCp.have_data_in) #define CMD_TAG(Cmnd) ((Cmnd)->SCp.sent_command) +#define CMD_FLAGS(Cmnd) ((Cmnd)->SCp.Status) #define FCPIO_INVALID_CODE 0x100 /* hdr_status value unused by firmware */ @@ -71,9 +85,28 @@ #define FNIC_HOST_RESET_TIMEOUT 1 /* mSec */ #define FNIC_RMDEVICE_TIMEOUT1000 /* mSec */ #define FNIC_HOST_RESET_SETTLE_TIME 30 /* Sec */ +#define FNIC_ABT_TERM_DELAY_TIMEOUT 500/* mSec */ #define FNIC_MAX_FCP_TARGET 256 +/** + * state_flags to identify host state along along with fnic's state + **/ +#define __FNIC_FLAGS_FWRESET BIT(0) /* fwreset in progress */ +#define __FNIC_FLAGS_BLOCK_IO BIT(1) /* IOs are blocked */ + +#define FNIC_FLAGS_NONE(0) +#define FNIC_FLAGS_FWRESET (__FNIC_FLAGS_FWRESET | \ + __FNIC_FLAGS_BLOCK_IO) + +#define FNIC_FLAGS_IO_BLOCKED (__FNIC_FLAGS_BLOCK_IO) + +#define fnic_set_state_flags(fnicp, st_flags) \ + __fnic_set_state_flags(fnicp, st_flags, 0) + +#define fnic_clear_state_flags(fnicp, st_flags) \ + __fnic_set_state_flags(fnicp, st_flags, 1) + extern unsigned int fnic_log_level; #define FNIC_MAIN_LOGGING 0x01 @@ -170,6 +203,9 @@ struct fnic { struct completion *remove_wait; /* device remove thread blocks */ + atomic_t in_flight; /* io counter */ + u32 _reserved; /* fill hole */ + unsigned long state_flags; /* protected by host lock */ enum fnic_state state; spinlock_t fnic_lock; @@ -267,4 +303,10 @@ const char *fnic_state_to_str(unsigned int state); void fnic_log_q_error(struct fnic *fnic); void fnic_handle_link_event(struct fnic *fnic); +static inline int +fnic_chk_state_flags_locked(
[PATCH 04/10] fnic: Fix SGEs limit
Driver allows IOs with more SGEs than max SGEs supported by Palo. The current max SGEs supported by the fnic driver is 1024. The current register settings on Palo supports a max of 256 only. Palo would return any IO with more than 256 SGEs with an error indicating INVALID_SGLS. Fnic driver should limit the max supported SGLs in the driver to 256 to avoid this error. Signed-off-by: Sesidhar Baddela Signed-off-by: Hiral Patel --- drivers/scsi/fnic/fnic_io.h |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/fnic/fnic_io.h b/drivers/scsi/fnic/fnic_io.h index f0b8969..3455c34 100644 --- a/drivers/scsi/fnic/fnic_io.h +++ b/drivers/scsi/fnic/fnic_io.h @@ -21,7 +21,7 @@ #include #define FNIC_DFLT_SG_DESC_CNT 32 -#define FNIC_MAX_SG_DESC_CNT1024/* Maximum descriptors per sgl */ +#define FNIC_MAX_SG_DESC_CNT256 /* Maximum descriptors per sgl */ #define FNIC_SG_DESC_ALIGN 16 /* Descriptor address alignment */ struct host_sg_desc { -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] Use a more selective error recovery strategy based on device capabilities
On 2/12/2013 2:57 PM, Elliott, Robert (Server Storage) wrote: > Ideally the device driver for the SCSI initiator port would report those > attributes, and higher level code would combine them with support > information from the device server (REPORT SUPPORTED TMF command, REPORT > SUPPORTED OPCODES command, etc.) to decide what is supported. Well, for the eh_xxx_handler functions, that is basically what happens now. The host driver can fail to set a callback for the eh_xxx_handlers if it doesn't support the operation. At that point, even if the target device supports a function (say target reset) if the host driver doesn't, then the target reset will be skipped. Of course, a number of the drivers define functions their underlying protocol's don't support. For example, bus reset on fibre channel. Which I personally believe is an error. -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH] Use a more selective error recovery strategy based on device capabilities
I like that concept. Since TMFs are protocol specific, though, it is possible that the SCSI initiator port doesn't know how to send a TMF even though the device server supports that TMF. The SCSI Architecture Model (SAM-5) standard includes an annex listing a variety of SCSI Initiator Port attributes and SCSI Target Port attributes that can limit what an application client and device server can do: - LUN size - Maximum CDB length - Command Identifier size (i.e. tag size) - Task Attributes supported (which ones) (e.g., SIMPLE, HEAD OF QUEUE, ORDERED, ACA) - Maximum Data-In Buffer size - Maximum Data-Out Buffer size - Command Reference Number supported? - Command Priority supported? - Maximum Sense Data length - Status Qualifier supported? - Additional Response Information supported? - Bidirectional Commands supported? - TMFs supported (which ones) How the application client determines what the SCSI initiator port supports is outside the scope of the SCSI standards - there's no SCSI command or TMF to report that information. These attributes are first constrained by the SCSI transport protocol (e.g., SRP doesn't define an encoding for QUERY TASK), then by implementation choices (e.g., bidirectional commands and >16-byte CDBs are still not widely supported). Ideally the device driver for the SCSI initiator port would report those attributes, and higher level code would combine them with support information from the device server (REPORT SUPPORTED TMF command, REPORT SUPPORTED OPCODES command, etc.) to decide what is supported. --- Rob ElliottHP Server Storage > -Original Message- > From: linux-scsi-ow...@vger.kernel.org [mailto:linux-scsi- > ow...@vger.kernel.org] On Behalf Of Jeremy Linton > Sent: Tuesday, 12 February, 2013 12:20 PM > To: Linux Scsi > Subject: [PATCH] Use a more selective error recovery strategy based on device > capabilities > > Ideally, Linux should not be sending task management commands to devices > that > don't support the given task mgmt operation. > > This patch uses the REPORT SUPPORTED TASK MGMT FUNCTIONS command to > enable or > disable error recovery paths for a given device. For older devices, we make an > educated guess about what kind of error recovery the device supports. This > isn't > going to be 100% accurate as it should probably take the transport as well as > the SCSI version into account, but it is a start. > > While this patch improves the error recovery paths for modern SCSI networks, > the > error recovery logic continues to fall through to host reset. It also > continues > to send bus and target resets in cases where they may affect working devices. > I > have a partial set of patches which attempt to make intelligent decisions in > these cases, but they are far more intrusive and at this point not as clear > cut. > > > Just in case... > Signed-off-by: Jeremy Linton > --- -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] Use a more selective error recovery strategy based on device capabilities
Ideally, Linux should not be sending task management commands to devices that don't support the given task mgmt operation. This patch uses the REPORT SUPPORTED TASK MGMT FUNCTIONS command to enable or disable error recovery paths for a given device. For older devices, we make an educated guess about what kind of error recovery the device supports. This isn't going to be 100% accurate as it should probably take the transport as well as the SCSI version into account, but it is a start. While this patch improves the error recovery paths for modern SCSI networks, the error recovery logic continues to fall through to host reset. It also continues to send bus and target resets in cases where they may affect working devices. I have a partial set of patches which attempt to make intelligent decisions in these cases, but they are far more intrusive and at this point not as clear cut. Just in case... Signed-off-by: Jeremy Linton --- diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index c1b05a8..b249c2f 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -572,24 +572,25 @@ static int scsi_try_host_reset(struct scsi_cmnd *scmd) static int scsi_try_bus_reset(struct scsi_cmnd *scmd) { unsigned long flags; - int rtn; + int rtn = FAILED ; struct Scsi_Host *host = scmd->device->host; struct scsi_host_template *hostt = host->hostt; + struct scsi_device *sdev = scmd->device; SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Bus RST\n", __func__)); - if (!hostt->eh_bus_reset_handler) - return FAILED; + if ((sdev->bus_reset_ok) && (hostt->eh_bus_reset_handler)) { - rtn = hostt->eh_bus_reset_handler(scmd); + rtn = hostt->eh_bus_reset_handler(scmd); - if (rtn == SUCCESS) { - if (!hostt->skip_settle_delay) - ssleep(BUS_RESET_SETTLE_TIME); - spin_lock_irqsave(host->host_lock, flags); - scsi_report_bus_reset(host, scmd_channel(scmd)); - spin_unlock_irqrestore(host->host_lock, flags); + if (rtn == SUCCESS) { + if (!hostt->skip_settle_delay) +ssleep(BUS_RESET_SETTLE_TIME); + spin_lock_irqsave(host->host_lock, flags); + scsi_report_bus_reset(host, scmd_channel(scmd)); + spin_unlock_irqrestore(host->host_lock, flags); + } } return rtn; @@ -601,6 +602,7 @@ static void __scsi_report_device_reset(struct scsi_device *sdev, void *data) sdev->expecting_cc_ua = 1; } + /** * scsi_try_target_reset - Ask host to perform a target reset * @scmd: SCSI cmd used to send a target reset @@ -614,19 +616,26 @@ static void __scsi_report_device_reset(struct scsi_device *sdev, void *data) static int scsi_try_target_reset(struct scsi_cmnd *scmd) { unsigned long flags; - int rtn; + int rtn = FAILED; + struct scsi_device *sdev = scmd->device; struct Scsi_Host *host = scmd->device->host; struct scsi_host_template *hostt = host->hostt; - if (!hostt->eh_target_reset_handler) - return FAILED; + if ((sdev->target_reset_ok) && (hostt->eh_target_reset_handler)) { - rtn = hostt->eh_target_reset_handler(scmd); - if (rtn == SUCCESS) { - spin_lock_irqsave(host->host_lock, flags); - __starget_for_each_device(scsi_target(scmd->device), NULL, - __scsi_report_device_reset); - spin_unlock_irqrestore(host->host_lock, flags); + // TODO: Determine if other devices on this IT are experiencing + // issues. If not, return success without doing anything. + SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd target RST\n", + __func__)); + + rtn = hostt->eh_target_reset_handler(scmd); + + if (rtn == SUCCESS) { + spin_lock_irqsave(host->host_lock, flags); + __starget_for_each_device(scsi_target(scmd->device), NULL, + __scsi_report_device_reset); + spin_unlock_irqrestore(host->host_lock, flags); + } } return rtn; @@ -644,24 +653,36 @@ static int scsi_try_target_reset(struct scsi_cmnd *scmd) */ static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd) { - int rtn; + int rtn = FAILED; struct scsi_host_template *hostt = scmd->device->host->hostt; + struct scsi_device *sdev = scmd->device; - if (!hostt->eh_device_reset_handler) - return FAILED; + if ((sdev->task_unit_reset_ok) && (hostt->eh_device_reset_handler)) { + SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd LUN RST\n", + __func__)); + rtn = hostt->eh_device_reset_handler(scmd); + + if (rtn == SUCCESS) + __scsi_report_device_reset(scmd->device, NULL); + } - rtn = hostt->eh_device_reset_handler(scmd); - if (rtn == SUCCESS) - __scsi_report_device_reset(scmd->device, NULL); return rtn; } static int scsi_try_to_abort_cmd(struct scsi_host_template *hostt, struct scsi_cmnd *scmd) { - if (!hostt->eh_abort_handler) - return FAILED; + int rtn = FAILED; + struct scsi_device *sdev = scmd->device; + + if ((sdev->task_abort_ok) && (hostt->eh_abort_handler)) + { + SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Host RST\n", + __func__)); - return hostt->eh_abort_handler(scmd); + rtn=hostt->eh_abort_handler(scmd); + } + + return rtn; } static void sc
Re: Incorrect LBA Returned from scsi_get_lba() and blk_rq_pos() (Possible DIF Impact)
> "Sami" == Sami Waheed writes: Sami> I am testing a SCSI/SAS target with a block size of 4K. I noticed Sami> that scsi_get_lba which calls blk_rq_pos is returning an incorrect Sami> LBA. The returned LBA value is 8x the actual LBA specified in the Sami> CDB: The block layer always uses 512-byte sectors internally, regardless of the logical block size of the actual disk. Sami> I, also, noticed that several drivers use the scsi_get_lba inline Sami> in scsi_cmnd.h to set/check ref tag for DIF. On a 4K device, this Sami> is resulting in an incorrect ref tag. I have some patches in the pipeline that fixes this. They also add support for protection intervals different from the logical block size. -- Martin K. Petersen Oracle Linux Engineering -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Incorrect LBA Returned from scsi_get_lba() and blk_rq_pos() (Possible DIF Impact)
Hello, I am testing a SCSI/SAS target with a block size of 4K.I noticed that scsi_get_lba which calls blk_rq_pos is returning an incorrect LBA. The returned LBA value is 8x the actual LBA specified in the CDB: The following "end_request:" message is printed from blk-core.c: [ 812.451579] sd 6:0:0:0: [sdb] [ 812.451582] Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE [ 812.451585] sd 6:0:0:0: [sdb] [ 812.451587] Sense Key : Aborted Command [current] [ 812.451591] sd 6:0:0:0: [sdb] [ 812.451593] Add. Sense: No additional sense information [ 812.451596] sd 6:0:0:0: [sdb] CDB: [ 812.451597] Write(10): 2a 20 00 00 03 e8 00 00 01 00 [ 812.451606] end_request: I/O error, dev sdb, sector 8000 Above CDB has LBA=0x3e8 which is 1000d. Printed sector size above is 8000d I, also, noticed that several drivers use the scsi_get_lba inline in scsi_cmnd.h to set/check ref tag for DIF. On a 4K device, this is resulting in an incorrect ref tag. Tested with kernel 3.7.5. Regards, --sami -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] qla2xxx: Update firmware link in Kconfig file.
Signed-off-by: Giridhar Malavali Signed-off-by: Chad Dupuis --- drivers/scsi/qla2xxx/Kconfig |4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig index 317a7fd..23d6072 100644 --- a/drivers/scsi/qla2xxx/Kconfig +++ b/drivers/scsi/qla2xxx/Kconfig @@ -24,7 +24,9 @@ config SCSI_QLA_FC Firmware images can be retrieved from: - ftp://ftp.qlogic.com/outgoing/linux/firmware/ + http://ldriver.qlogic.com/firmware/ + + They are also included in the linux-firmware tree as well. config TCM_QLA2XXX tristate "TCM_QLA2XXX fabric module for Qlogic 2xxx series target mode HBAs" -- 1.7.7 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] scsi_debug: Fix endianess in partition table
On 13-02-12 04:03 AM, Martin Peschke wrote: On Mon, 2013-02-11 at 18:34 +0100, Martin Peschke wrote: Both start_sect and nr_sects in struct partition are __le32 and require cpu_to_le32() on assignment. Steffen Maier has pointed me at: block/partitions/msdos.c: return (sector_t)get_unaligned_le32(&p->start_sect); Unfortunately, both get_unaligned_le32() and le32_to_cpu() appear to be in use for start_sect and nr_sects. Any one who would argue for changing my patch from cpu_to_le32 to put_unaligned_le32()? No (because I don't know). However since SCSI is big endian and you are introducing some "le" code then a line or so of explanation (comments) in your revised patch might be helpful. BTW Finding a big endian architecture to test this patch on is not easy. The openwrt in my router is big endian (MIPS) but openwrt don't distribute the scsi_debug module :-( Doug Gilbert Without this fix tools like fdisk show an invalid partition table for SCSI devices emulated by scsi_debug on big-endian architectures, like s390x. Besides a kernel message like this was emitted: sda: p1 start 536870912 is beyond EOD, enabling native capacity sda: p1 start 536870912 is beyond EOD, truncated For verification 'xxd -l 512 /dev/sda' has been used to make sure that this fix makes scsi_debug generated partition tables on s390x look like the ones generated on my laptop. Signed-off-by: Martin Peschke Reviewed-by: Steffen Maier --- drivers/scsi/scsi_debug.c |4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -2662,8 +2662,8 @@ static void __init sdebug_build_parts(un / sdebug_sectors_per; pp->end_sector = (end_sec % sdebug_sectors_per) + 1; - pp->start_sect = start_sec; - pp->nr_sects = end_sec - start_sec + 1; + pp->start_sect = cpu_to_le32(start_sec); + pp->nr_sects = cpu_to_le32(end_sec - start_sec + 1); pp->sys_ind = 0x83; /* plain Linux partition */ } } -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 06/23] qla2xxx: Update the FTP site references in the driver sources.
On Mon, 11 Feb 2013, Xose Vazquez Perez wrote: Giridhar Malavali wrote: From: Giridhar Malavali Signed-off-by: Giridhar Malavali Signed-off-by: Saurav Kashyap --- drivers/scsi/qla2xxx/qla_init.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index a581c85..bbf5688 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -5054,7 +5054,7 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, return rval; } -#define QLA_FW_URL "ftp://ftp.qlogic.com/outgoing/linux/firmware/"; +#define QLA_FW_URL "http://ldriver.qlogic.com/firmware/"; int qla2x00_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr) -- qla2xxx/Kconfig should also be changed: Firmware images can be retrieved from: ftp://ftp.qlogic.com/outgoing/linux/firmware/ FYI, they are also included in linux-firmware. Thanks for pointing this out Xose. We'll be posting a patch soon to fix the firmware link in the Kconfig files. -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html This message and any attached documents contain information from QLogic Corporation or its wholly-owned subsidiaries that may be confidential. If you are not the intended recipient, you may not read, copy, distribute, or use this information. If you have received this transmission in error, please notify the sender immediately by reply e-mail and then delete this message. -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 0/5] virtio-scsi multiqueue
This series implements virtio-scsi queue steering, which gives performance improvements of up to 50% (measured both with QEMU and tcm_vhost backends). The patches build on top of the new virtio APIs at http://permalink.gmane.org/gmane.linux.kernel.virtualization/18431; the new API simplifies the locking of the virtio-scsi driver nicely, thus it makes sense to require them as a prerequisite. Changes from the previous post, which can be found at http://permalink.gmane.org/gmane.linux.kernel.virtualization/17869: - patches 1 and 2 ("virtio: add functions for piecewise addition of buffers", "virtio-scsi: use functions for piecewise composition of buffers") split into their own series - new cleanup patch "virtio-scsi: push vq lock/unlock into virtscsi_vq_done" - reorganized code to move ACCESS_ONCE in a clearer place - included Wanlong Gao's CPU hotplug patches Ok for 3.9? It would probably be easier to get it in via Rusty's tree because of the prerequisites. James, can I get your Acked-by? Paolo Paolo Bonzini (4): virtio-scsi: redo allocation of target data virtio-scsi: pass struct virtio_scsi to virtqueue completion function virtio-scsi: push vq lock/unlock into virtscsi_vq_done virtio-scsi: introduce multiqueue support Wanlong Gao (1): virtio-scsi: reset virtqueue affinity when doing cpu hotplug drivers/scsi/virtio_scsi.c | 360 +++- 1 files changed, 292 insertions(+), 68 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 5/5] virtio-scsi: reset virtqueue affinity when doing cpu hotplug
From: Wanlong Gao Add hot cpu notifier to reset the request virtqueue affinity when doing cpu hotplug. Cc: linux-scsi@vger.kernel.org Signed-off-by: Wanlong Gao [ The version that doesn't get/put_online_cpus is now called __virtscsi_set_affinity - Paolo ] Signed-off-by: Paolo Bonzini --- drivers/scsi/virtio_scsi.c | 31 +++ 1 files changed, 31 insertions(+), 0 deletions(-) diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index a2bdae1..733307a 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -109,6 +110,9 @@ struct virtio_scsi { /* Does the affinity hint is set for virtqueues? */ bool affinity_hint_set; + /* CPU hotplug notifier */ + struct notifier_block nb; + struct virtio_scsi_vq ctrl_vq; struct virtio_scsi_vq event_vq; struct virtio_scsi_vq req_vqs[]; @@ -734,6 +738,7 @@ static void __virtscsi_set_affinity(struct virtio_scsi *vscsi, bool affinity) } } + static void virtscsi_set_affinity(struct virtio_scsi *vscsi, bool affinity) { get_online_cpus(); @@ -741,6 +746,23 @@ static void virtscsi_set_affinity(struct virtio_scsi *vscsi, bool affinity) put_online_cpus(); } +static int virtscsi_cpu_callback(struct notifier_block *nfb, +unsigned long action, void *hcpu) +{ + struct virtio_scsi *vscsi = container_of(nfb, struct virtio_scsi, nb); + switch(action) { + case CPU_ONLINE: + case CPU_ONLINE_FROZEN: + case CPU_DEAD: + case CPU_DEAD_FROZEN: + __virtscsi_set_affinity(vscsi, true); + break; + default: + break; + } + return NOTIFY_OK; +} + static void virtscsi_init_vq(struct virtio_scsi_vq *virtscsi_vq, struct virtqueue *vq) { @@ -885,6 +907,13 @@ static int virtscsi_probe(struct virtio_device *vdev) if (err) goto virtscsi_init_failed; + vscsi->nb.notifier_call = &virtscsi_cpu_callback; + err = register_hotcpu_notifier(&vscsi->nb); + if (err) { + pr_err("virtio_scsi: registering cpu notifier failed\n"); + goto scsi_add_host_failed; + } + cmd_per_lun = virtscsi_config_get(vdev, cmd_per_lun) ?: 1; shost->cmd_per_lun = min_t(u32, cmd_per_lun, shost->can_queue); shost->max_sectors = virtscsi_config_get(vdev, max_sectors) ?: 0x; @@ -922,6 +951,8 @@ static void virtscsi_remove(struct virtio_device *vdev) scsi_remove_host(shost); + unregister_hotcpu_notifier(&vscsi->nb); + virtscsi_remove_vqs(vdev); scsi_host_put(shost); } -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 3/5] virtio-scsi: push vq lock/unlock into virtscsi_vq_done
Avoid duplicated code in all of the callers. Cc: linux-scsi@vger.kernel.org Signed-off-by: Paolo Bonzini --- drivers/scsi/virtio_scsi.c | 22 +- 1 files changed, 9 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 3dd4ec5..3d77210 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -165,28 +165,30 @@ static void virtscsi_complete_cmd(struct virtio_scsi *vscsi, void *buf) sc->scsi_done(sc); } -static void virtscsi_vq_done(struct virtio_scsi *vscsi, struct virtqueue *vq, +static void virtscsi_vq_done(struct virtio_scsi *vscsi, +struct virtio_scsi_vq *virtscsi_vq, void (*fn)(struct virtio_scsi *vscsi, void *buf)) { void *buf; unsigned int len; + unsigned long flags; + struct virtqueue *vq = virtscsi_vq->vq; + spin_lock_irqsave(&virtscsi_vq->vq_lock, flags); do { virtqueue_disable_cb(vq); while ((buf = virtqueue_get_buf(vq, &len)) != NULL) fn(vscsi, buf); } while (!virtqueue_enable_cb(vq)); + spin_unlock_irqrestore(&virtscsi_vq->vq_lock, flags); } static void virtscsi_req_done(struct virtqueue *vq) { struct Scsi_Host *sh = virtio_scsi_host(vq->vdev); struct virtio_scsi *vscsi = shost_priv(sh); - unsigned long flags; - spin_lock_irqsave(&vscsi->req_vq.vq_lock, flags); - virtscsi_vq_done(vscsi, vq, virtscsi_complete_cmd); - spin_unlock_irqrestore(&vscsi->req_vq.vq_lock, flags); + virtscsi_vq_done(vscsi, &vscsi->req_vq, virtscsi_complete_cmd); }; static void virtscsi_complete_free(struct virtio_scsi *vscsi, void *buf) @@ -203,11 +205,8 @@ static void virtscsi_ctrl_done(struct virtqueue *vq) { struct Scsi_Host *sh = virtio_scsi_host(vq->vdev); struct virtio_scsi *vscsi = shost_priv(sh); - unsigned long flags; - spin_lock_irqsave(&vscsi->ctrl_vq.vq_lock, flags); - virtscsi_vq_done(vscsi, vq, virtscsi_complete_free); - spin_unlock_irqrestore(&vscsi->ctrl_vq.vq_lock, flags); + virtscsi_vq_done(vscsi, &vscsi->ctrl_vq, virtscsi_complete_free); }; static int virtscsi_kick_event(struct virtio_scsi *vscsi, @@ -342,11 +341,8 @@ static void virtscsi_event_done(struct virtqueue *vq) { struct Scsi_Host *sh = virtio_scsi_host(vq->vdev); struct virtio_scsi *vscsi = shost_priv(sh); - unsigned long flags; - spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags); - virtscsi_vq_done(vscsi, vq, virtscsi_complete_event); - spin_unlock_irqrestore(&vscsi->event_vq.vq_lock, flags); + virtscsi_vq_done(vscsi, &vscsi->event_vq, virtscsi_complete_event); }; /** -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 4/5] virtio-scsi: introduce multiqueue support
This patch adds queue steering to virtio-scsi. When a target is sent multiple requests, we always drive them to the same queue so that FIFO processing order is kept. However, if a target was idle, we can choose a queue arbitrarily. In this case the queue is chosen according to the current VCPU, so the driver expects the number of request queues to be equal to the number of VCPUs. This makes it easy and fast to select the queue, and also lets the driver optimize the IRQ affinity for the virtqueues (each virtqueue's affinity is set to the CPU that "owns" the queue). The speedup comes from improving cache locality and giving CPU affinity to the virtqueues, which is why this scheme was selected. Assuming that the thread that is sending requests to the device is I/O-bound, it is likely to be sleeping at the time the ISR is executed, and thus executing the ISR on the same processor that sent the requests is cheap. However, the kernel will not execute the ISR on the "best" processor unless you explicitly set the affinity. This is because in practice you will have many such I/O-bound processes and thus many otherwise idle processors. Then the kernel will execute the ISR on a random processor, rather than the one that is sending requests to the device. The alternative to per-CPU virtqueues is per-target virtqueues. To achieve the same locality, we could dynamically choose the virtqueue's affinity based on the CPU of the last task that sent a request. This is less appealing because we do not set the affinity directly---we only provide a hint to the irqbalanced running in userspace. Dynamically changing the affinity only works if the userspace applies the hint fast enough. Cc: linux-scsi@vger.kernel.org Signed-off-by: Wanlong Gao Signed-off-by: Paolo Bonzini --- drivers/scsi/virtio_scsi.c | 269 +++- 1 files changed, 240 insertions(+), 29 deletions(-) diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 3d77210..a2bdae1 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -26,6 +26,7 @@ #define VIRTIO_SCSI_MEMPOOL_SZ 64 #define VIRTIO_SCSI_EVENT_LEN 8 +#define VIRTIO_SCSI_VQ_BASE 2 /* Command queue element */ struct virtio_scsi_cmd { @@ -57,24 +58,60 @@ struct virtio_scsi_vq { struct virtqueue *vq; }; -/* Per-target queue state */ +/* + * Per-target queue state. + * + * This struct holds the data needed by the queue steering policy. When a + * target is sent multiple requests, we need to drive them to the same queue so + * that FIFO processing order is kept. However, if a target was idle, we can + * choose a queue arbitrarily. In this case the queue is chosen according to + * the current VCPU, so the driver expects the number of request queues to be + * equal to the number of VCPUs. This makes it easy and fast to select the + * queue, and also lets the driver optimize the IRQ affinity for the virtqueues + * (each virtqueue's affinity is set to the CPU that "owns" the queue). + * + * An interesting effect of this policy is that only writes to req_vq need to + * take the tgt_lock. Read can be done outside the lock because: + * + * - writes of req_vq only occur when atomic_inc_return(&tgt->reqs) returns 1. + * In that case, no other CPU is reading req_vq: even if they were in + * virtscsi_queuecommand_multi, they would be spinning on tgt_lock. + * + * - reads of req_vq only occur when the target is not idle (reqs != 0). + * A CPU that enters virtscsi_queuecommand_multi will not modify req_vq. + * + * Similarly, decrements of reqs are never concurrent with writes of req_vq. + * Thus they can happen outside the tgt_lock, provided of course we make reqs + * an atomic_t. + */ struct virtio_scsi_target_state { - /* Never held at the same time as vq_lock. */ + /* This spinlock ever held at the same time as vq_lock. */ spinlock_t tgt_lock; + + /* Count of outstanding requests. */ + atomic_t reqs; + + /* Currently active virtqueue for requests sent to this target. */ + struct virtio_scsi_vq *req_vq; }; /* Driver instance state */ struct virtio_scsi { struct virtio_device *vdev; - struct virtio_scsi_vq ctrl_vq; - struct virtio_scsi_vq event_vq; - struct virtio_scsi_vq req_vq; - /* Get some buffers ready for event vq */ struct virtio_scsi_event_node event_list[VIRTIO_SCSI_EVENT_LEN]; struct virtio_scsi_target_state *tgt; + + u32 num_queues; + + /* Does the affinity hint is set for virtqueues? */ + bool affinity_hint_set; + + struct virtio_scsi_vq ctrl_vq; + struct virtio_scsi_vq event_vq; + struct virtio_scsi_vq req_vqs[]; }; static struct kmem_cache *virtscsi_cmd_cache; @@ -109,6 +146,7 @@ static void virtscsi_complete_cmd(struct virtio_scsi *vscsi, void *buf) struct virtio_scsi_cmd *cmd = buf; struct scsi_cmnd *sc = cmd->sc; s
[PATCH v3 2/5] virtio-scsi: pass struct virtio_scsi to virtqueue completion function
This will be needed soon in order to retrieve the per-target struct. Cc: linux-scsi@vger.kernel.org Signed-off-by: Paolo Bonzini --- drivers/scsi/virtio_scsi.c | 17 + 1 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 3f15568..3dd4ec5 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -104,7 +104,7 @@ static void virtscsi_compute_resid(struct scsi_cmnd *sc, u32 resid) * * Called with vq_lock held. */ -static void virtscsi_complete_cmd(void *buf) +static void virtscsi_complete_cmd(struct virtio_scsi *vscsi, void *buf) { struct virtio_scsi_cmd *cmd = buf; struct scsi_cmnd *sc = cmd->sc; @@ -165,7 +165,8 @@ static void virtscsi_complete_cmd(void *buf) sc->scsi_done(sc); } -static void virtscsi_vq_done(struct virtqueue *vq, void (*fn)(void *buf)) +static void virtscsi_vq_done(struct virtio_scsi *vscsi, struct virtqueue *vq, +void (*fn)(struct virtio_scsi *vscsi, void *buf)) { void *buf; unsigned int len; @@ -173,7 +174,7 @@ static void virtscsi_vq_done(struct virtqueue *vq, void (*fn)(void *buf)) do { virtqueue_disable_cb(vq); while ((buf = virtqueue_get_buf(vq, &len)) != NULL) - fn(buf); + fn(vscsi, buf); } while (!virtqueue_enable_cb(vq)); } @@ -184,11 +185,11 @@ static void virtscsi_req_done(struct virtqueue *vq) unsigned long flags; spin_lock_irqsave(&vscsi->req_vq.vq_lock, flags); - virtscsi_vq_done(vq, virtscsi_complete_cmd); + virtscsi_vq_done(vscsi, vq, virtscsi_complete_cmd); spin_unlock_irqrestore(&vscsi->req_vq.vq_lock, flags); }; -static void virtscsi_complete_free(void *buf) +static void virtscsi_complete_free(struct virtio_scsi *vscsi, void *buf) { struct virtio_scsi_cmd *cmd = buf; @@ -205,7 +206,7 @@ static void virtscsi_ctrl_done(struct virtqueue *vq) unsigned long flags; spin_lock_irqsave(&vscsi->ctrl_vq.vq_lock, flags); - virtscsi_vq_done(vq, virtscsi_complete_free); + virtscsi_vq_done(vscsi, vq, virtscsi_complete_free); spin_unlock_irqrestore(&vscsi->ctrl_vq.vq_lock, flags); }; @@ -329,7 +330,7 @@ static void virtscsi_handle_event(struct work_struct *work) virtscsi_kick_event(vscsi, event_node); } -static void virtscsi_complete_event(void *buf) +static void virtscsi_complete_event(struct virtio_scsi *vscsi, void *buf) { struct virtio_scsi_event_node *event_node = buf; @@ -344,7 +345,7 @@ static void virtscsi_event_done(struct virtqueue *vq) unsigned long flags; spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags); - virtscsi_vq_done(vq, virtscsi_complete_event); + virtscsi_vq_done(vscsi, vq, virtscsi_complete_event); spin_unlock_irqrestore(&vscsi->event_vq.vq_lock, flags); }; -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 1/5] virtio-scsi: redo allocation of target data
virtio_scsi_target_state is now empty, but we will find new uses for it in the next few patches. However, dropping the sglist lets us turn the array-of-pointers into a simple array, which simplifies the allocation. However, we do not leave the virtio_scsi_target_state structs in the flexible array member at the end of struct virtio_scsi, because we will place the virtqueues there in the next patches. Cc: linux-scsi@vger.kernel.org Signed-off-by: Paolo Bonzini --- drivers/scsi/virtio_scsi.c | 39 --- 1 files changed, 12 insertions(+), 27 deletions(-) diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 8b90c17..3f15568 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -74,7 +74,7 @@ struct virtio_scsi { /* Get some buffers ready for event vq */ struct virtio_scsi_event_node event_list[VIRTIO_SCSI_EVENT_LEN]; - struct virtio_scsi_target_state *tgt[]; + struct virtio_scsi_target_state *tgt; }; static struct kmem_cache *virtscsi_cmd_cache; @@ -574,19 +574,9 @@ static void virtscsi_init_vq(struct virtio_scsi_vq *virtscsi_vq, virtscsi_vq->vq = vq; } -static struct virtio_scsi_target_state *virtscsi_alloc_tgt( - struct virtio_device *vdev, int sg_elems) +static void virtscsi_init_tgt(struct virtio_scsi_target_state *tgt) { - struct virtio_scsi_target_state *tgt; - gfp_t gfp_mask = GFP_KERNEL; - - /* We need extra sg elements at head and tail. */ - tgt = kmalloc(sizeof(*tgt), gfp_mask); - if (!tgt) - return NULL; - spin_lock_init(&tgt->tgt_lock); - return tgt; } static void virtscsi_scan(struct virtio_device *vdev) @@ -600,16 +590,12 @@ static void virtscsi_remove_vqs(struct virtio_device *vdev) { struct Scsi_Host *sh = virtio_scsi_host(vdev); struct virtio_scsi *vscsi = shost_priv(sh); - u32 i, num_targets; /* Stop all the virtqueues. */ vdev->config->reset(vdev); - num_targets = sh->max_id; - for (i = 0; i < num_targets; i++) { - kfree(vscsi->tgt[i]); - vscsi->tgt[i] = NULL; - } + kfree(vscsi->tgt); + vscsi->tgt = NULL; vdev->config->del_vqs(vdev); } @@ -650,13 +636,14 @@ static int virtscsi_init(struct virtio_device *vdev, /* We need to know how many segments before we allocate. */ sg_elems = virtscsi_config_get(vdev, seg_max) ?: 1; - for (i = 0; i < num_targets; i++) { - vscsi->tgt[i] = virtscsi_alloc_tgt(vdev, sg_elems); - if (!vscsi->tgt[i]) { - err = -ENOMEM; - goto out; - } + vscsi->tgt = kmalloc(num_targets * sizeof(vscsi->tgt[0]), GFP_KERNEL); + if (!vscsi->tgt) { + err = -ENOMEM; + goto out; } + for (i = 0; i < num_targets; i++) + virtscsi_init_tgt(&vscsi->tgt[i]); + err = 0; out: @@ -675,9 +662,7 @@ static int virtscsi_probe(struct virtio_device *vdev) /* Allocate memory and link the structs together. */ num_targets = virtscsi_config_get(vdev, max_target) + 1; - shost = scsi_host_alloc(&virtscsi_host_template, - sizeof(*vscsi) - + num_targets * sizeof(struct virtio_scsi_target_state)); + shost = scsi_host_alloc(&virtscsi_host_template, sizeof(*vscsi)); if (!shost) return -ENOMEM; -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 15/15] pm80xx: thermal, sas controller config and error handling update
>From 9c620d9273640b416054ba76cd267aebaf455ed2 Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Wed, 6 Feb 2013 17:39:43 +0530 Subject: [PATCH 15/15] pm80xx: thermal, sas controller config and error handling update Modified thermal configuration to happen after interrupt registration Added SAS controller configuration during initialization Added error handling logic to handle I_T_Nexus errors and variants Signed-off-by: Anand Kumar S --- drivers/scsi/pm8001/pm8001_hwi.c |2 +- drivers/scsi/pm8001/pm8001_init.c |2 + drivers/scsi/pm8001/pm8001_sas.c | 66 drivers/scsi/pm8001/pm8001_sas.h |2 + drivers/scsi/pm8001/pm80xx_hwi.c | 150 + drivers/scsi/pm8001/pm80xx_hwi.h | 44 +++- 6 files changed, 249 insertions(+), 17 deletions(-) diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index a90c002..d18f421 100755 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -1670,7 +1670,7 @@ void pm8001_work_fn(struct work_struct *work) } break; case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: dev = pm8001_dev->sas_device; - pm8001_I_T_nexus_reset(dev); + pm8001_I_T_nexus_event_handler(dev); break; case IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY: dev = pm8001_dev->sas_device; diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index b884a58..289c2a5 100755 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -1795,6 +1795,8 @@ static int pm8001_pci_probe(struct pci_dev *pdev, if (pm8001_ha->chip_id != chip_8001) { for (i = 1; i < pm8001_ha->number_of_intr; i++) PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, i); + /* setup thermal configuration. */ + pm80xx_set_thermal_config(pm8001_ha); } pm8001_init_sas_add(pm8001_ha); diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index c720917..9af9585 100755 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -1018,6 +1018,72 @@ int pm8001_I_T_nexus_reset(struct domain_device *dev) return rc; } +/* +* This function handle the IT_NEXUS_XXX event or completion +* status code for SSP/SATA/SMP I/O request. +*/ +int pm8001_I_T_nexus_event_handler(struct domain_device *dev) +{ + int rc = TMF_RESP_FUNC_FAILED; + struct pm8001_device *pm8001_dev; + struct pm8001_hba_info *pm8001_ha; + struct sas_phy *phy; + u32 device_id = 0; + + if (!dev || !dev->lldd_dev) + return -1; + + pm8001_dev = dev->lldd_dev; + device_id = pm8001_dev->device_id; + pm8001_ha = pm8001_find_ha_by_dev(dev); + + PM8001_EH_DBG(pm8001_ha, + pm8001_printk("I_T_Nexus handler invoked !!")); + + phy = sas_get_local_phy(dev); + + if (dev_is_sata(dev)) { + DECLARE_COMPLETION_ONSTACK(completion_setstate); + if (scsi_is_sas_phy_local(phy)) { + rc = 0; + goto out; + } + /* send internal ssp/sata/smp abort command to FW */ + rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev , + dev, 1, 0); + msleep(100); + + /* deregister the target device */ + pm8001_dev_gone_notify(dev); + msleep(200); + + /*send phy reset to hard reset target */ + rc = sas_phy_reset(phy, 1); + msleep(2000); + pm8001_dev->setds_completion = &completion_setstate; + + wait_for_completion(&completion_setstate); + } else { + /* send internal ssp/sata/smp abort command to FW */ + rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev , + dev, 1, 0); + msleep(100); + + /* deregister the target device */ + pm8001_dev_gone_notify(dev); + msleep(200); + + /*send phy reset to hard reset target */ + rc = sas_phy_reset(phy, 1); + msleep(2000); + } + PM8001_EH_DBG(pm8001_ha, pm8001_printk(" for device[%x]:rc=%d\n", + pm8001_dev->device_id, rc)); +out: + sas_put_local_phy(phy); + + return rc; +} /* mandatory SAM-3, the task reset the specified LUN*/ int pm8001_lu_reset(struct domain_device *dev, u8 *lun) { diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index c1598dc..fbb65d5 100755 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h @@ -562,6 +562,7 @@ int pm8001_dev_found(struct domain_device *dev); void pm8001_dev_gone(struct do
[PATCH 14/15] pm80xx: NCQ error handling changes
>From 97d4edce607941e931b77d1fed12096294ff6c8e Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Wed, 6 Feb 2013 17:27:22 +0530 Subject: [PATCH 14/15] pm80xx: NCQ error handling changes Handled NCQ errors in the low level driver as the FW is not providing the faulty tag for NCQ errors for libsas to recover. Signed-off-by: Anand Kumar S --- drivers/scsi/pm8001/pm8001_hwi.c | 270 -- drivers/scsi/pm8001/pm8001_sas.c | 22 +++- drivers/scsi/pm8001/pm8001_sas.h | 15 ++- drivers/scsi/pm8001/pm80xx_hwi.c | 262 +++-- drivers/scsi/pm8001/pm80xx_hwi.h |1 + 5 files changed, 543 insertions(+), 27 deletions(-) diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 265dbf4..a90c002 100755 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -1707,6 +1707,123 @@ int pm8001_handle_event(struct pm8001_hba_info *pm8001_ha, void *data, return ret; } +static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha, + struct pm8001_device *pm8001_ha_dev) +{ + int res; + u32 ccb_tag; + struct pm8001_ccb_info *ccb; + struct sas_task *task = NULL; + struct task_abort_req task_abort; + struct inbound_queue_table *circularQ; + u32 opc = OPC_INB_SATA_ABORT; + int ret; + + if (!pm8001_ha_dev) { + PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("dev is null \n")); + return; + } + + task = sas_alloc_slow_task(GFP_ATOMIC); + + if (!task) { + PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("cannot " + "allocate task \n")); + return; + } + + task->task_done = pm8001_task_done; + + res = pm8001_tag_alloc(pm8001_ha, &ccb_tag); + if (res) + return; + + ccb = &pm8001_ha->ccb_info[ccb_tag]; + ccb->device = pm8001_ha_dev; + ccb->ccb_tag = ccb_tag; + ccb->task = task; + + circularQ = &pm8001_ha->inbnd_q_tbl[0]; + + memset(&task_abort, 0, sizeof(task_abort)); + task_abort.abort_all = cpu_to_le32(1); + task_abort.device_id = cpu_to_le32(pm8001_ha_dev->device_id); + task_abort.tag = cpu_to_le32(ccb_tag); + + ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0); + +} + +static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha, + struct pm8001_device *pm8001_ha_dev) +{ + struct sata_start_req sata_cmd; + int res; + u32 ccb_tag; + struct pm8001_ccb_info *ccb; + struct sas_task *task = NULL; + struct host_to_dev_fis fis; + struct domain_device *dev; + struct inbound_queue_table *circularQ; + u32 opc = OPC_INB_SATA_HOST_OPSTART; + + task = sas_alloc_slow_task(GFP_ATOMIC); + + if (!task) { + PM8001_FAIL_DBG(pm8001_ha, + pm8001_printk("cannot allocate task !!!\n")); + return; + } + task->task_done = pm8001_task_done; + + res = pm8001_tag_alloc(pm8001_ha, &ccb_tag); + if (res) { + PM8001_FAIL_DBG(pm8001_ha, + pm8001_printk("cannot allocate tag !!!\n")); + return; + } + + /* allocate domain device by ourselves as libsas +* is not going to provide any + */ + dev = kzalloc(sizeof(struct domain_device), GFP_ATOMIC); + if (!dev) { + PM8001_FAIL_DBG(pm8001_ha, + pm8001_printk("Domain device cannot be allocated \n")); + sas_free_task(task); + return; + } else { + task->dev = dev; + task->dev->lldd_dev = pm8001_ha_dev; + } + + ccb = &pm8001_ha->ccb_info[ccb_tag]; + ccb->device = pm8001_ha_dev; + ccb->ccb_tag = ccb_tag; + ccb->task = task; + pm8001_ha_dev->id |= NCQ_READ_LOG_FLAG; + pm8001_ha_dev->id |= NCQ_2ND_RLE_FLAG; + + memset(&sata_cmd, 0, sizeof(sata_cmd)); + circularQ = &pm8001_ha->inbnd_q_tbl[0]; + + /* construct read log FIS */ + memset(&fis, 0, sizeof(struct host_to_dev_fis)); + fis.fis_type = 0x27; + fis.flags = 0x80; + fis.command = ATA_CMD_READ_LOG_EXT; + fis.lbal = 0x10; + fis.sector_count = 0x1; + + sata_cmd.tag = cpu_to_le32(ccb_tag); + sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id); + sata_cmd.ncqtag_atap_dir_m |= ((0x1 << 7) | (0x5 << 9)); + memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis)); + + res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0); + +} + /** * mpi_ssp_completion- process the event that FW response to the SSP request. * @pm8001_ha: our hba card information @@ -2170,16 +2287,44 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) status = le32_to_c
[PATCH 13/15] pm80xx: WWN Modification for PM8081/88/89 controllers
>From 43681f8bc5a857318ead1a9173d6b796f238738c Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Tue, 5 Feb 2013 12:07:19 +0530 Subject: [PATCH 13/15] pm80xx: WWN Modification for PM8081/88/89 controllers Individual WWN read operations based on controller. PM8081 - Read WWN from Flash VPD. PM8088/89 - Read WWN from EEPROM. PM8001 - Read WWN from NVM. Signed-off-by: Sakthivel K Signed-off-by: Anand Kumar S --- drivers/scsi/pm8001/pm8001_init.c | 43 +++-- 1 files changed, 36 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index a9e6db0..b884a58 100755 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -1566,21 +1566,50 @@ static void pm8001_post_sas_ha_init(struct Scsi_Host *shost, */ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) { - u8 i; + u8 i, j; #ifdef PM8001_READ_VPD + /* For new SPC controllers WWN is stored in flash vpd + * For SPC/SPCve controllers WWN is stored in EEPROM + * For Older SPC WWN is stored in NVMD + */ DECLARE_COMPLETION_ONSTACK(completion); struct pm8001_ioctl_payload payload; + u16 deviceid; + pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid); pm8001_ha->nvmd_completion = &completion; - payload.minor_function = 0; - payload.length = 128; - payload.func_specific = kzalloc(128, GFP_KERNEL); + + if (pm8001_ha->chip_id == chip_8001) { + if (deviceid == 0x8081) { + payload.minor_function = 4; + payload.length = 4096; + } else { + payload.minor_function = 0; + payload.length = 128; + } + } else { + payload.minor_function = 1; + payload.length = 4096; + } + payload.offset = 0; + payload.func_specific = kzalloc(payload.length, GFP_KERNEL); PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload); wait_for_completion(&completion); + + for (i = 0, j = 0; i <= 7; i++, j++) { + if (pm8001_ha->chip_id == chip_8001) { + if (deviceid == 0x8081) + pm8001_ha->sas_addr[j] = + payload.func_specific[0x704 + i]; + } else + pm8001_ha->sas_addr[j] = + payload.func_specific[0x804 + i]; + } + for (i = 0; i < pm8001_ha->chip->n_phy; i++) { - memcpy(&pm8001_ha->phy[i].dev_sas_addr, pm8001_ha->sas_addr, - SAS_ADDR_SIZE); + memcpy(&pm8001_ha->phy[i].dev_sas_addr, + pm8001_ha->sas_addr, SAS_ADDR_SIZE); PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("phy %d sas_addr = %016llx \n", i, + pm8001_printk("phy %d sas_addr = %016llx\n", i, pm8001_ha->phy[i].dev_sas_addr)); } #else -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 12/15] pm80xx: Changed module name and debug messages update
>From 78eaee73dd18671795fb6781bb34dc4c5e3410ce Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Tue, 5 Feb 2013 11:48:05 +0530 Subject: [PATCH 12/15] pm80xx: Changed module name and debug messages update Changed name in driver to pm80xx. Updated debug messages. Signed-off-by: Sakthivel K Signed-off-by: Anand Kumar S --- drivers/scsi/pm8001/Makefile |7 --- drivers/scsi/pm8001/pm8001_hwi.c | 11 ++- drivers/scsi/pm8001/pm8001_init.c | 14 ++ drivers/scsi/pm8001/pm8001_sas.h |6 +++--- 4 files changed, 23 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/pm8001/Makefile b/drivers/scsi/pm8001/Makefile index 52f0429..ce4cd87 100755 --- a/drivers/scsi/pm8001/Makefile +++ b/drivers/scsi/pm8001/Makefile @@ -4,9 +4,10 @@ # Copyright (C) 2008-2009 USI Co., Ltd. -obj-$(CONFIG_SCSI_PM8001) += pm8001.o -pm8001-y += pm8001_init.o \ +obj-$(CONFIG_SCSI_PM8001) += pm80xx.o +pm80xx-y += pm8001_init.o \ pm8001_sas.o \ pm8001_ctl.o \ - pm8001_hwi.o + pm8001_hwi.o \ + pm80xx_hwi.o diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index c124fc6..265dbf4 100755 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -2506,9 +2506,9 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) if (unlikely(!t || !t->lldd_task || !t->dev)) return; ts = &t->task_status; - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("port_id = %x,device_id = %x\n", - port_id, dev_id)); + PM8001_IO_DBG(pm8001_ha, pm8001_printk( + "port_id:0x%x, device_id:0x%x, tag:0x%x, event:0x%x\n", + port_id, dev_id, tag, event)); switch (event) { case IO_OVERFLOW: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n")); @@ -4409,8 +4409,9 @@ int pm8001_chip_abort_task(struct pm8001_hba_info *pm8001_ha, { u32 opc, device_id; int rc = TMF_RESP_FUNC_FAILED; - PM8001_EH_DBG(pm8001_ha, pm8001_printk("cmd_tag = %x, abort task tag" - " = %x", cmd_tag, task_tag)); + PM8001_EH_DBG(pm8001_ha, + pm8001_printk("cmd_tag = %x, abort task tag = 0x%x", + cmd_tag, task_tag)); if (pm8001_dev->dev_type == SAS_END_DEV) opc = OPC_INB_SSP_ABORT; else if (pm8001_dev->dev_type == SATA_DEV) diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index cb17cb9..a9e6db0 100755 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -1698,7 +1698,7 @@ static int pm8001_pci_probe(struct pci_dev *pdev, const struct pm8001_chip_info *chip; dev_printk(KERN_INFO, &pdev->dev, - "pm8001: driver version %s\n", DRV_VERSION); + "pm80xx: driver version %s\n", DRV_VERSION); rc = pci_enable_device(pdev); if (rc) goto err_out_enable; @@ -1746,15 +1746,21 @@ static int pm8001_pci_probe(struct pci_dev *pdev, list_add_tail(&pm8001_ha->list, &hba_list); PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha); rc = PM8001_CHIP_DISP->chip_init(pm8001_ha); - if (rc) + if (rc) { + PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( + "chip_init failed [ret: %d]\n", rc)); goto err_out_ha_free; + } rc = scsi_add_host(shost, &pdev->dev); if (rc) goto err_out_ha_free; rc = pm8001_request_irq(pm8001_ha); - if (rc) + if (rc) { + PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( + "pm8001_request_irq failed [ret: %d]\n", rc)); goto err_out_shost; + } PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, 0); if (pm8001_ha->chip_id != chip_8001) { @@ -2131,7 +2137,7 @@ static int __init pm8001_init(void) { int rc = -ENOMEM; - pm8001_wq = alloc_workqueue("pm8001", 0, 0); + pm8001_wq = alloc_workqueue("pm80xx", 0, 0); if (!pm8001_wq) goto err; diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index 466934d..53d7f3b 100755 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h @@ -57,7 +57,7 @@ #include #include "pm8001_defs.h" -#define DRV_NAME "pm8001" +#define DRV_NAME "pm80xx" #define DRV_VERSION"0.1.36" #define PM8001_FAIL_LOGGING0x01 /* Error message logging */ #define PM8001_INIT_LOGGING0x02 /* driver init logging */ @@ -66,8 +66,8 @@ #define PM8001_EH_LOGGING 0x10 /* libsas EH function logging*/ #define PM8001_IOCTL_LOGGING 0x20 /* IOCTL message logging */ #define PM8001_MSG_LOGGING 0x40 /* misc message logging */ -#define pm8001_printk(format, arg...) printk(KERN_INFO "%s %d:" form
[PATCH 11/15] pm80xx: Firmware flash memory free fix, with addition of new memory, region for it
>From d3f1b3ea4b638f154a7979773f6a839fa455564b Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Tue, 5 Feb 2013 11:06:51 +0530 Subject: [PATCH 11/15] pm80xx: Firmware flash memory free fix, with addition of new memory region for it Performing pci_free_consistent in tasklet had result in a core dump. So allocated a new memory region for it. Fix for passing proper address and operation in firmware flash update. Signed-off-by: Sakthivel K Signed-off-by: Anand Kumar S --- drivers/scsi/pm8001/pm8001_ctl.c |5 +++-- drivers/scsi/pm8001/pm8001_defs.h |3 ++- drivers/scsi/pm8001/pm8001_hwi.c | 30 ++ drivers/scsi/pm8001/pm8001_init.c |3 +++ 4 files changed, 14 insertions(+), 27 deletions(-) diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c index ae2b124..d99f41c 100755 --- a/drivers/scsi/pm8001/pm8001_ctl.c +++ b/drivers/scsi/pm8001/pm8001_ctl.c @@ -400,10 +400,11 @@ static int pm8001_set_nvmd(struct pm8001_hba_info *pm8001_ha) goto out; } payload = (struct pm8001_ioctl_payload *)ioctlbuffer; - memcpy((u8 *)payload->func_specific, (u8 *)pm8001_ha->fw_image->data, + memcpy((u8 *)&payload->func_specific, (u8 *)pm8001_ha->fw_image->data, pm8001_ha->fw_image->size); payload->length = pm8001_ha->fw_image->size; payload->id = 0; + payload->minor_function = 0x1; pm8001_ha->nvmd_completion = &completion; ret = PM8001_CHIP_DISP->set_nvmd_req(pm8001_ha, payload); wait_for_completion(&completion); @@ -450,7 +451,7 @@ static int pm8001_update_flash(struct pm8001_hba_info *pm8001_ha) payload->length = 1024*16; payload->id = 0; fwControl = - (struct fw_control_info *)payload->func_specific; + (struct fw_control_info *)&payload->func_specific; fwControl->len = IOCTL_BUF_SIZE; /* IN */ fwControl->size = partitionSize + HEADER_LEN;/* IN */ fwControl->retcode = 0;/* OUT */ diff --git a/drivers/scsi/pm8001/pm8001_defs.h b/drivers/scsi/pm8001/pm8001_defs.h index 26a2ee6..479c5a7 100755 --- a/drivers/scsi/pm8001/pm8001_defs.h +++ b/drivers/scsi/pm8001/pm8001_defs.h @@ -86,7 +86,7 @@ enum port_type { #definePM8001_MAX_DEVICES 2048 /* max supported device */ #definePM8001_MAX_MSIX_VEC 64 /* max msi-x int for spcv/ve */ -#define USI_MAX_MEMCNT_BASE4 +#define USI_MAX_MEMCNT_BASE5 #define IB (USI_MAX_MEMCNT_BASE + 1) #define CI (IB + PM8001_MAX_SPCV_INB_NUM) #define OB (CI + PM8001_MAX_SPCV_INB_NUM) @@ -99,6 +99,7 @@ enum memory_region_num { NVMD, /* NVM device */ DEV_MEM,/* memory for devices */ CCB_MEM,/* memory for command control block */ + FW_FLASH/* memory for fw flash update */ }; #definePM8001_EVENT_LOG_SIZE(128 * 1024) diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 3adf499..c124fc6 100755 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -3481,10 +3481,6 @@ int pm8001_mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha, break; } ccb->fw_control_context->fw_control->retcode = status; - pci_free_consistent(pm8001_ha->pdev, - fw_control_context.len, - fw_control_context.virtAddr, - fw_control_context.phys_addr); complete(pm8001_ha->nvmd_completion); ccb->task = NULL; ccb->ccb_tag = 0x; @@ -4474,7 +4470,7 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha, fw_control_context = kzalloc(sizeof(struct fw_control_ex), GFP_KERNEL); if (!fw_control_context) return -ENOMEM; - fw_control_context->usrAddr = (u8 *)&ioctl_payload->func_specific[0]; + fw_control_context->usrAddr = (u8 *)ioctl_payload->func_specific; fw_control_context->len = ioctl_payload->length; circularQ = &pm8001_ha->inbnd_q_tbl[0]; memset(&nvmd_req, 0, sizeof(nvmd_req)); @@ -4556,7 +4552,7 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha, return -ENOMEM; circularQ = &pm8001_ha->inbnd_q_tbl[0]; memcpy(pm8001_ha->memoryMap.region[NVMD].virt_ptr, - ioctl_payload->func_specific, + &ioctl_payload->func_specific, ioctl_payload->length); memset(&nvmd_req, 0, sizeof(nvmd_req)); rc = pm8001_tag_alloc(pm8001_ha, &tag); @@ -4658,29 +4654,14 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha, int rc; u32 tag; struct pm8001_ccb_info *ccb; - void *buffer = NULL; -
[PATCH 00/15] Support for PMC 8081/8088/8089 controllers
James/Linux-scsi, The following patchset provides support for PMC 8081/88/89 series of controllers. >From 9c620d9273640b416054ba76cd267aebaf455ed2 Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Thu, 7 Feb 2013 17:03:42 +0530 Subject: [PATCH 00/15] Support for PMC 8081/8088/8089 controllers. Support for PMC 8081/8088/8089 series of controllers. New data structures and hardware functionality files have been added to support 8088/8089 controllers. The hardware specific file contains new functionality specific to 8088/8089 controllers including support for encryption, thermal settings, FW upgradation. Since 8081/8088/8089 controllers are built on top of 8001 controller most of the data structures and functions of 8001 controller are reused. MSI-X support for 8081/8088/8089 and many more error handling logic to handle controller specific errors have been introduced. Functionality to support multiple inbound and outbound queues have been added for 8088/8089 controllers. Fixes for 8001 driver include memory region fix, NCQ error handling logic, WWN number retrieval for the controller. In addition new memory regions have been introduced for FW flash. Sakthivel K (15): pm80xx: fix for memory region free pm80xx: Added vendor and device ids for SPCv/SPCve controllers pm80xx: Added and modified structures, variables and macros for SPCv/ve pm80xx: Structure and variable name update for SPC pm80xx: Multiple inbound/outbound queue configuration pm80xx: Updated common functions common for SPC and SPCv/ve pm80xx: MSI-X implementation for using 64 interrupts pm80xx: Added SPCv/ve specific hardware functionalities pm80xx: SPCv/ve specific changes in common files pm80xx: SPC new firmware changes for device id 0x8081 alone pm80xx: Firmware flash memory free fix, with addition of new memory region for it pm80xx: Changed module name and debug messages update pm80xx: WWN Modification for PM8081/88/89 controllers pm80xx: NCQ error handling changes pm80xx: thermal, sas controller config and error handling update drivers/scsi/pm8001/Makefile |7 +- drivers/scsi/pm8001/pm8001_ctl.c | 74 +- drivers/scsi/pm8001/pm8001_defs.h | 34 +- drivers/scsi/pm8001/pm8001_hwi.c | 796 +--- drivers/scsi/pm8001/pm8001_hwi.h |4 +- drivers/scsi/pm8001/pm8001_init.c | 1478 +- drivers/scsi/pm8001/pm8001_sas.c | 105 +- drivers/scsi/pm8001/pm8001_sas.h | 176 ++- drivers/scsi/pm8001/pm80xx_hwi.c | 4131 + drivers/scsi/pm8001/pm80xx_hwi.h | 1524 ++ 10 files changed, 7937 insertions(+), 392 deletions(-) create mode 100644 drivers/scsi/pm8001/pm80xx_hwi.c create mode 100644 drivers/scsi/pm8001/pm80xx_hwi.h -Anand -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 10/15] pm80xx: SPC new firmware changes for device id 0x8081 alone
>From 954868e338b75c829fb85e6596383b26e34b56e3 Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Tue, 5 Feb 2013 11:18:23 +0530 Subject: [PATCH 10/15] pm80xx: SPC new firmware changes for device id 0x8081 alone Additional bar shift for new SPC firmware, applicable to device id 0x8081 only. Signed-off-by: Sakthivel K Signed-off-by: Anand Kumar S --- drivers/scsi/pm8001/pm8001_hwi.c | 31 --- drivers/scsi/pm8001/pm8001_hwi.h |2 ++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index c335ae8..3adf499 100755 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -640,6 +640,18 @@ static void init_pci_device_addresses(struct pm8001_hba_info *pm8001_ha) static int pm8001_chip_init(struct pm8001_hba_info *pm8001_ha) { u8 i = 0; + u16 deviceid; + pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid); + /* 8081 controllers need BAR shift to access MPI space + * as this is shared with BIOS data */ + if (deviceid == 0x8081) { + if (-1 == pm8001_bar4_shift(pm8001_ha, GSM_SM_BASE)) { + PM8001_FAIL_DBG(pm8001_ha, + pm8001_printk("Shift Bar4 to 0x%x failed\n", + GSM_SM_BASE)); + return -1; + } + } /* check the firmware status */ if (-1 == check_fw_ready(pm8001_ha)) { PM8001_FAIL_DBG(pm8001_ha, @@ -660,9 +672,12 @@ static int pm8001_chip_init(struct pm8001_hba_info *pm8001_ha) update_inbnd_queue_table(pm8001_ha, i); for (i = 0; i < PM8001_MAX_OUTB_NUM; i++) update_outbnd_queue_table(pm8001_ha, i); - mpi_set_phys_g3_with_ssc(pm8001_ha, 0); - /* 7->130ms, 34->500ms, 119->1.5s */ - mpi_set_open_retry_interval_reg(pm8001_ha, 119); + /* 8081 controller donot require these operations */ + if (deviceid != 0x8081) { + mpi_set_phys_g3_with_ssc(pm8001_ha, 0); + /* 7->130ms, 34->500ms, 119->1.5s */ + mpi_set_open_retry_interval_reg(pm8001_ha, 119); + } /* notify firmware update finished and check initialization status */ if (0 == mpi_init_check(pm8001_ha)) { PM8001_INIT_DBG(pm8001_ha, @@ -684,6 +699,16 @@ static int mpi_uninit_check(struct pm8001_hba_info *pm8001_ha) u32 max_wait_count; u32 value; u32 gst_len_mpistate; + u16 deviceid; + pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid); + if (deviceid == 0x8081) { + if (-1 == pm8001_bar4_shift(pm8001_ha, GSM_SM_BASE)) { + PM8001_FAIL_DBG(pm8001_ha, + pm8001_printk("Shift Bar4 to 0x%x failed\n", + GSM_SM_BASE)); + return -1; + } + } init_pci_device_addresses(pm8001_ha); /* Write bit1=1 to Inbound DoorBell Register to tell the SPC FW the table is stop */ diff --git a/drivers/scsi/pm8001/pm8001_hwi.h b/drivers/scsi/pm8001/pm8001_hwi.h index 2399aab..d7c1e20 100755 --- a/drivers/scsi/pm8001/pm8001_hwi.h +++ b/drivers/scsi/pm8001/pm8001_hwi.h @@ -131,6 +131,8 @@ #define LINKRATE_30(0x02 << 8) #define LINKRATE_60(0x04 << 8) +/* for new SPC controllers MEMBASE III is shared between BIOS and DATA */ +#define GSM_SM_BASE0x4F struct mpi_msg_hdr{ __le32 header; /* Bits [11:0] - Message operation code */ /* Bits [15:12] - Message Category */ -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 09/15] pm80xx: SPCv/ve specific changes in common files
>From 14c5d89e766cab606b067d0ded2baa8836414e8a Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Tue, 5 Feb 2013 11:00:39 +0530 Subject: [PATCH 09/15] pm80xx: SPCv/ve specific changes in common files Changing common functionalities for SPCv/ve operations. Conditional checks for SPC specific operations. Signed-off-by: Sakthivel K Signed-off-by: Anand Kumar S --- drivers/scsi/pm8001/pm8001_hwi.c |4 ++-- drivers/scsi/pm8001/pm8001_hwi.h |2 +- drivers/scsi/pm8001/pm8001_init.c | 13 + drivers/scsi/pm8001/pm8001_sas.c | 17 +++-- drivers/scsi/pm8001/pm8001_sas.h |4 ++-- 5 files changed, 25 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 26f5197..c335ae8 100755 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -785,14 +785,14 @@ static u32 soft_reset_ready_check(struct pm8001_hba_info *pm8001_ha) * pm8001_chip_soft_rst - soft reset the PM8001 chip, so that the clear all * the FW register status to the originated status. * @pm8001_ha: our hba card information - * @signature: signature in host scratch pad0 register. */ static int -pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha, u32 signature) +pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) { u32 regVal, toggleVal; u32 max_wait_count; u32 regVal1, regVal2, regVal3; + u32 signature = 0x252acbcd; /* for host scratch pad0 */ unsigned long flags; /* step1: Check FW is ready for soft reset */ diff --git a/drivers/scsi/pm8001/pm8001_hwi.h b/drivers/scsi/pm8001/pm8001_hwi.h index d437309..2399aab 100755 --- a/drivers/scsi/pm8001/pm8001_hwi.h +++ b/drivers/scsi/pm8001/pm8001_hwi.h @@ -298,7 +298,7 @@ struct local_phy_ctl_resp { #define OP_BITS 0xFF00 -#define ID_BITS 0x000F +#define ID_BITS 0x00FF /* * brief the data structure of PORT Control Command diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index f0c5075..9dcd72c 100755 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -1741,7 +1741,7 @@ static int pm8001_pci_probe(struct pci_dev *pdev, goto err_out_free; } list_add_tail(&pm8001_ha->list, &hba_list); - PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha, 0x252acbcd); + PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha); rc = PM8001_CHIP_DISP->chip_init(pm8001_ha); if (rc) goto err_out_ha_free; @@ -1795,7 +1795,7 @@ static void pm8001_pci_remove(struct pci_dev *pdev) list_del(&pm8001_ha->list); scsi_remove_host(pm8001_ha->shost); PM8001_CHIP_DISP->interrupt_disable(pm8001_ha, 0xFF); - PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha, 0x252acbcd); + PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha); #ifdef PM8001_USE_MSIX for (i = 0; i < pm8001_ha->number_of_intr; i++) @@ -1843,7 +1843,7 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state) return -ENODEV; } PM8001_CHIP_DISP->interrupt_disable(pm8001_ha, 0xFF); - PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha, 0x252acbcd); + PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha); #ifdef PM8001_USE_MSIX for (i = 0; i < pm8001_ha->number_of_intr; i++) synchronize_irq(pm8001_ha->msix_entries[i].vector); @@ -1904,7 +1904,12 @@ static int pm8001_pci_resume(struct pci_dev *pdev) if (rc) goto err_out_disable; - PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha, 0x252acbcd); + /* chip soft rst only for spc */ + if (pm8001_ha->chip_id == chip_8001) { + PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha); + PM8001_INIT_DBG(pm8001_ha, + pm8001_printk("chip soft reset successful\n")); + } rc = PM8001_CHIP_DISP->chip_init(pm8001_ha); if (rc) goto err_out_disable; diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index b961112..6bba59c 100755 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -1,5 +1,5 @@ /* - * PMC-Sierra SPC 8001 SAS/SATA based host adapters driver + * PMC-Sierra PM8001/8081/8088/8089 SAS/SATA based host adapters driver * * Copyright (c) 2008-2009 USI Co., Ltd. * All rights reserved. @@ -212,10 +212,12 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, break; case PHY_FUNC_GET_EVENTS: spin_lock_irqsave(&pm8001_ha->lock, flags); - if (-1 == pm8001_bar4_shift(pm8001_ha, + if (pm8001_ha->chip_id == chip_8001) { + if (-1 == pm8001_bar4_shift(pm8001_ha, (phy_id < 4) ? 0x3 : 0x4)) { - spin_unlock_irqrestore(&pm8001_ha->lock, flags); - return -E
[PATCH 07/15] pm80xx: MSI-X implementation for using 64 interrupts
>From 952973b812c65eb2a7d70ed8c333b7837fb39191 Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Mon, 4 Feb 2013 18:02:22 +0530 Subject: [PATCH 07/15] pm80xx: MSI-X implementation for using 64 interrupts Implementation of 64 interrupt handlers and tasklets to support upto 64 interrupt for the device. Signed-off-by: Sakthivel K Signed-off-by: Anand Kumar S --- drivers/scsi/pm8001/pm8001_init.c | 1233 - 1 files changed, 1203 insertions(+), 30 deletions(-) diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index e8a983f..f0c5075 100755 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -163,7 +163,13 @@ static void pm8001_free(struct pm8001_hba_info *pm8001_ha) } #ifdef PM8001_USE_TASKLET -static void pm8001_tasklet(unsigned long opaque) + +/** + * tasklets for 64 msi-x interrupt handlers + * @opaque: the passed general host adapter struct + * Note: pm8001_tasklet0 is common for pm8001 & pm80xx + */ +static void pm8001_tasklet0(unsigned long opaque) { struct pm8001_hba_info *pm8001_ha; pm8001_ha = (struct pm8001_hba_info *)opaque; @@ -171,16 +177,521 @@ static void pm8001_tasklet(unsigned long opaque) BUG_ON(1); PM8001_CHIP_DISP->isr(pm8001_ha, 0); } +static void pm8001_tasklet1(unsigned long opaque) +{ + struct pm8001_hba_info *pm8001_ha; + pm8001_ha = (struct pm8001_hba_info *)opaque; + if (unlikely(!pm8001_ha)) + BUG_ON(1); + PM8001_CHIP_DISP->isr(pm8001_ha, 1); +} +static void pm8001_tasklet2(unsigned long opaque) +{ + struct pm8001_hba_info *pm8001_ha; + pm8001_ha = (struct pm8001_hba_info *)opaque; + if (unlikely(!pm8001_ha)) + BUG_ON(1); + PM8001_CHIP_DISP->isr(pm8001_ha, 2); +} +static void pm8001_tasklet3(unsigned long opaque) +{ + struct pm8001_hba_info *pm8001_ha; + pm8001_ha = (struct pm8001_hba_info *)opaque; + if (unlikely(!pm8001_ha)) + BUG_ON(1); + PM8001_CHIP_DISP->isr(pm8001_ha, 3); +} +static void pm8001_tasklet4(unsigned long opaque) +{ + struct pm8001_hba_info *pm8001_ha; + pm8001_ha = (struct pm8001_hba_info *)opaque; + if (unlikely(!pm8001_ha)) + BUG_ON(1); + PM8001_CHIP_DISP->isr(pm8001_ha, 4); +} +static void pm8001_tasklet5(unsigned long opaque) +{ + struct pm8001_hba_info *pm8001_ha; + pm8001_ha = (struct pm8001_hba_info *)opaque; + if (unlikely(!pm8001_ha)) + BUG_ON(1); + PM8001_CHIP_DISP->isr(pm8001_ha, 5); +} +static void pm8001_tasklet6(unsigned long opaque) +{ + struct pm8001_hba_info *pm8001_ha; + pm8001_ha = (struct pm8001_hba_info *)opaque; + if (unlikely(!pm8001_ha)) + BUG_ON(1); + PM8001_CHIP_DISP->isr(pm8001_ha, 6); +} +static void pm8001_tasklet7(unsigned long opaque) +{ + struct pm8001_hba_info *pm8001_ha; + pm8001_ha = (struct pm8001_hba_info *)opaque; + if (unlikely(!pm8001_ha)) + BUG_ON(1); + PM8001_CHIP_DISP->isr(pm8001_ha, 7); +} +static void pm8001_tasklet8(unsigned long opaque) +{ + struct pm8001_hba_info *pm8001_ha; + pm8001_ha = (struct pm8001_hba_info *)opaque; + if (unlikely(!pm8001_ha)) + BUG_ON(1); + PM8001_CHIP_DISP->isr(pm8001_ha, 8); +} +static void pm8001_tasklet9(unsigned long opaque) +{ + struct pm8001_hba_info *pm8001_ha; + pm8001_ha = (struct pm8001_hba_info *)opaque; + if (unlikely(!pm8001_ha)) + BUG_ON(1); + PM8001_CHIP_DISP->isr(pm8001_ha, 9); +} +static void pm8001_tasklet10(unsigned long opaque) +{ + struct pm8001_hba_info *pm8001_ha; + pm8001_ha = (struct pm8001_hba_info *)opaque; + if (unlikely(!pm8001_ha)) + BUG_ON(1); + PM8001_CHIP_DISP->isr(pm8001_ha, 10); +} +static void pm8001_tasklet11(unsigned long opaque) +{ + struct pm8001_hba_info *pm8001_ha; + pm8001_ha = (struct pm8001_hba_info *)opaque; + if (unlikely(!pm8001_ha)) + BUG_ON(1); + PM8001_CHIP_DISP->isr(pm8001_ha, 11); +} +static void pm8001_tasklet12(unsigned long opaque) +{ + struct pm8001_hba_info *pm8001_ha; + pm8001_ha = (struct pm8001_hba_info *)opaque; + if (unlikely(!pm8001_ha)) + BUG_ON(1); + PM8001_CHIP_DISP->isr(pm8001_ha, 12); +} +static void pm8001_tasklet13(unsigned long opaque) +{ + struct pm8001_hba_info *pm8001_ha; + pm8001_ha = (struct pm8001_hba_info *)opaque; + if (unlikely(!pm8001_ha)) + BUG_ON(1); + PM8001_CHIP_DISP->isr(pm8001_ha, 13); +} +static void pm8001_tasklet14(unsigned long opaque) +{ + struct pm8001_hba_info *pm8001_ha; + pm8001_ha = (struct pm8001_hba_info *)opaque; + if (unlikely(!pm8001_ha)) + BUG_ON(1); + PM8001_CHIP_DISP->isr(pm8001_ha, 14); +} +static void pm8001_tasklet15
[PATCH 07/15] pm80xx: MSI-X implementation for using 64 interrupts
>From 952973b812c65eb2a7d70ed8c333b7837fb39191 Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Mon, 4 Feb 2013 18:02:22 +0530 Subject: [PATCH 07/15] pm80xx: MSI-X implementation for using 64 interrupts Implementation of 64 interrupt handlers and tasklets to support upto 64 interrupt for the device. Signed-off-by: Sakthivel K Signed-off-by: Anand Kumar S --- drivers/scsi/pm8001/pm8001_init.c | 1233 - 1 files changed, 1203 insertions(+), 30 deletions(-) diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index e8a983f..f0c5075 100755 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -163,7 +163,13 @@ static void pm8001_free(struct pm8001_hba_info *pm8001_ha) } #ifdef PM8001_USE_TASKLET -static void pm8001_tasklet(unsigned long opaque) + +/** + * tasklets for 64 msi-x interrupt handlers + * @opaque: the passed general host adapter struct + * Note: pm8001_tasklet0 is common for pm8001 & pm80xx + */ +static void pm8001_tasklet0(unsigned long opaque) { struct pm8001_hba_info *pm8001_ha; pm8001_ha = (struct pm8001_hba_info *)opaque; @@ -171,16 +177,521 @@ static void pm8001_tasklet(unsigned long opaque) BUG_ON(1); PM8001_CHIP_DISP->isr(pm8001_ha, 0); } +static void pm8001_tasklet1(unsigned long opaque) +{ + struct pm8001_hba_info *pm8001_ha; + pm8001_ha = (struct pm8001_hba_info *)opaque; + if (unlikely(!pm8001_ha)) + BUG_ON(1); + PM8001_CHIP_DISP->isr(pm8001_ha, 1); +} +static void pm8001_tasklet2(unsigned long opaque) +{ + struct pm8001_hba_info *pm8001_ha; + pm8001_ha = (struct pm8001_hba_info *)opaque; + if (unlikely(!pm8001_ha)) + BUG_ON(1); + PM8001_CHIP_DISP->isr(pm8001_ha, 2); +} +static void pm8001_tasklet3(unsigned long opaque) +{ + struct pm8001_hba_info *pm8001_ha; + pm8001_ha = (struct pm8001_hba_info *)opaque; + if (unlikely(!pm8001_ha)) + BUG_ON(1); + PM8001_CHIP_DISP->isr(pm8001_ha, 3); +} +static void pm8001_tasklet4(unsigned long opaque) +{ + struct pm8001_hba_info *pm8001_ha; + pm8001_ha = (struct pm8001_hba_info *)opaque; + if (unlikely(!pm8001_ha)) + BUG_ON(1); + PM8001_CHIP_DISP->isr(pm8001_ha, 4); +} +static void pm8001_tasklet5(unsigned long opaque) +{ + struct pm8001_hba_info *pm8001_ha; + pm8001_ha = (struct pm8001_hba_info *)opaque; + if (unlikely(!pm8001_ha)) + BUG_ON(1); + PM8001_CHIP_DISP->isr(pm8001_ha, 5); +} +static void pm8001_tasklet6(unsigned long opaque) +{ + struct pm8001_hba_info *pm8001_ha; + pm8001_ha = (struct pm8001_hba_info *)opaque; + if (unlikely(!pm8001_ha)) + BUG_ON(1); + PM8001_CHIP_DISP->isr(pm8001_ha, 6); +} +static void pm8001_tasklet7(unsigned long opaque) +{ + struct pm8001_hba_info *pm8001_ha; + pm8001_ha = (struct pm8001_hba_info *)opaque; + if (unlikely(!pm8001_ha)) + BUG_ON(1); + PM8001_CHIP_DISP->isr(pm8001_ha, 7); +} +static void pm8001_tasklet8(unsigned long opaque) +{ + struct pm8001_hba_info *pm8001_ha; + pm8001_ha = (struct pm8001_hba_info *)opaque; + if (unlikely(!pm8001_ha)) + BUG_ON(1); + PM8001_CHIP_DISP->isr(pm8001_ha, 8); +} +static void pm8001_tasklet9(unsigned long opaque) +{ + struct pm8001_hba_info *pm8001_ha; + pm8001_ha = (struct pm8001_hba_info *)opaque; + if (unlikely(!pm8001_ha)) + BUG_ON(1); + PM8001_CHIP_DISP->isr(pm8001_ha, 9); +} +static void pm8001_tasklet10(unsigned long opaque) +{ + struct pm8001_hba_info *pm8001_ha; + pm8001_ha = (struct pm8001_hba_info *)opaque; + if (unlikely(!pm8001_ha)) + BUG_ON(1); + PM8001_CHIP_DISP->isr(pm8001_ha, 10); +} +static void pm8001_tasklet11(unsigned long opaque) +{ + struct pm8001_hba_info *pm8001_ha; + pm8001_ha = (struct pm8001_hba_info *)opaque; + if (unlikely(!pm8001_ha)) + BUG_ON(1); + PM8001_CHIP_DISP->isr(pm8001_ha, 11); +} +static void pm8001_tasklet12(unsigned long opaque) +{ + struct pm8001_hba_info *pm8001_ha; + pm8001_ha = (struct pm8001_hba_info *)opaque; + if (unlikely(!pm8001_ha)) + BUG_ON(1); + PM8001_CHIP_DISP->isr(pm8001_ha, 12); +} +static void pm8001_tasklet13(unsigned long opaque) +{ + struct pm8001_hba_info *pm8001_ha; + pm8001_ha = (struct pm8001_hba_info *)opaque; + if (unlikely(!pm8001_ha)) + BUG_ON(1); + PM8001_CHIP_DISP->isr(pm8001_ha, 13); +} +static void pm8001_tasklet14(unsigned long opaque) +{ + struct pm8001_hba_info *pm8001_ha; + pm8001_ha = (struct pm8001_hba_info *)opaque; + if (unlikely(!pm8001_ha)) + BUG_ON(1); + PM8001_CHIP_DISP->isr(pm8001_ha, 14); +} +static void pm8001_tasklet15(u
[PATCH 06/15] pm80xx: Updated common functions common for SPC and SPCv/ve
>From 3fd0f7b1b3d82fc3a55dbfad6e9708ad64f17369 Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Mon, 4 Feb 2013 17:32:34 +0530 Subject: [PATCH 06/15] pm80xx: Updated common functions common for SPC and SPCv/ve Update of function prototype for common function to SPC and SPCv/ve. Multiple queues implementation for IO. Signed-off-by: Sakthivel K Signed-off-by: Anand Kumar S --- drivers/scsi/pm8001/pm8001_hwi.c | 193 +++-- drivers/scsi/pm8001/pm8001_init.c | 20 +++-- drivers/scsi/pm8001/pm8001_sas.h | 60 +++- 3 files changed, 168 insertions(+), 105 deletions(-) diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 651834c..26f5197 100755 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -1158,7 +1158,7 @@ static void pm8001_hw_chip_rst(struct pm8001_hba_info *pm8001_ha) * pm8001_chip_iounmap - which maped when initialized. * @pm8001_ha: our hba card information */ -static void pm8001_chip_iounmap(struct pm8001_hba_info *pm8001_ha) +void pm8001_chip_iounmap(struct pm8001_hba_info *pm8001_ha) { s8 bar, logical = 0; for (bar = 0; bar < 6; bar++) { @@ -1237,7 +1237,7 @@ pm8001_chip_msix_interrupt_disable(struct pm8001_hba_info *pm8001_ha, * @pm8001_ha: our hba card information */ static void -pm8001_chip_interrupt_enable(struct pm8001_hba_info *pm8001_ha) +pm8001_chip_interrupt_enable(struct pm8001_hba_info *pm8001_ha, u8 vec) { #ifdef PM8001_USE_MSIX pm8001_chip_msix_interrupt_enable(pm8001_ha, 0); @@ -1252,7 +1252,7 @@ pm8001_chip_interrupt_enable(struct pm8001_hba_info *pm8001_ha) * @pm8001_ha: our hba card information */ static void -pm8001_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha) +pm8001_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha, u8 vec) { #ifdef PM8001_USE_MSIX pm8001_chip_msix_interrupt_disable(pm8001_ha, 0); @@ -1263,12 +1263,13 @@ pm8001_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha) } /** - * mpi_msg_free_get- get the free message buffer for transfer inbound queue. + * pm8001_mpi_msg_free_get - get the free message buffer for transfer + * inbound queue. * @circularQ: the inbound queue we want to transfer to HBA. * @messageSize: the message size of this transfer, normally it is 64 bytes * @messagePtr: the pointer to message. */ -static int mpi_msg_free_get(struct inbound_queue_table *circularQ, +int pm8001_mpi_msg_free_get(struct inbound_queue_table *circularQ, u16 messageSize, void **messagePtr) { u32 offset, consumer_index; @@ -1276,7 +1277,7 @@ static int mpi_msg_free_get(struct inbound_queue_table *circularQ, u8 bcCount = 1; /* only support single buffer */ /* Checks is the requested message size can be allocated in this queue*/ - if (messageSize > 64) { + if (messageSize > IOMB_SIZE_SPCV) { *messagePtr = NULL; return -1; } @@ -1290,7 +1291,7 @@ static int mpi_msg_free_get(struct inbound_queue_table *circularQ, return -1; } /* get memory IOMB buffer address */ - offset = circularQ->producer_idx * 64; + offset = circularQ->producer_idx * messageSize; /* increment to next bcCount element */ circularQ->producer_idx = (circularQ->producer_idx + bcCount) % PM8001_MPI_QUEUE; @@ -1302,29 +1303,30 @@ static int mpi_msg_free_get(struct inbound_queue_table *circularQ, } /** - * mpi_build_cmd- build the message queue for transfer, update the PI to FW - * to tell the fw to get this message from IOMB. + * pm8001_mpi_build_cmd- build the message queue for transfer, update the PI to + * FW to tell the fw to get this message from IOMB. * @pm8001_ha: our hba card information * @circularQ: the inbound queue we want to transfer to HBA. * @opCode: the operation code represents commands which LLDD and fw recognized. * @payload: the command payload of each operation command. */ -static int mpi_build_cmd(struct pm8001_hba_info *pm8001_ha, +int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha, struct inbound_queue_table *circularQ, -u32 opCode, void *payload) +u32 opCode, void *payload, u32 responseQueue) { u32 Header = 0, hpriority = 0, bc = 1, category = 0x02; - u32 responseQueue = 0; void *pMessage; - if (mpi_msg_free_get(circularQ, 64, &pMessage) < 0) { + if (pm8001_mpi_msg_free_get(circularQ, pm8001_ha->iomb_size, + &pMessage) < 0) { PM8001_IO_DBG(pm8001_ha, pm8001_printk("No free mpi buffer\n")); return -1; } BUG_ON(!payload); /*Copy to the payload*/ - memcpy(pMessage, payload, (64 - sizeof(struct mpi_msg_hdr))); + memcpy(pMessage, payload, (pm8001_ha->iomb_size - +
[PATCH 05/15] pm80xx: Multiple inbound/outbound queue
>From ea8e9d56a8f94fbf1963d9b56783a3f1cb743c1f Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Mon, 4 Feb 2013 16:31:43 +0530 Subject: [PATCH 05/15] pm80xx: Multiple inbound/outbound queue configuration Memory allocation and configuration of multiple inbound and outbound queues. Signed-off-by: Sakthivel K Signed-off-by: Anand Kumar S --- drivers/scsi/pm8001/pm8001_defs.h | 14 +++-- drivers/scsi/pm8001/pm8001_hwi.c | 43 drivers/scsi/pm8001/pm8001_init.c | 101 + 3 files changed, 98 insertions(+), 60 deletions(-) diff --git a/drivers/scsi/pm8001/pm8001_defs.h b/drivers/scsi/pm8001/pm8001_defs.h index b25f87c..26a2ee6 100755 --- a/drivers/scsi/pm8001/pm8001_defs.h +++ b/drivers/scsi/pm8001/pm8001_defs.h @@ -48,8 +48,7 @@ enum chip_flavors { chip_8018, chip_8019 }; -#define USI_MAX_MEMCNT 9 -#define PM8001_MAX_DMA_SG SG_ALL + enum phy_speed { PHY_SPEED_15 = 0x01, PHY_SPEED_30 = 0x02, @@ -87,13 +86,16 @@ enum port_type { #definePM8001_MAX_DEVICES 2048 /* max supported device */ #definePM8001_MAX_MSIX_VEC 64 /* max msi-x int for spcv/ve */ +#define USI_MAX_MEMCNT_BASE4 +#define IB (USI_MAX_MEMCNT_BASE + 1) +#define CI (IB + PM8001_MAX_SPCV_INB_NUM) +#define OB (CI + PM8001_MAX_SPCV_INB_NUM) +#define PI (OB + PM8001_MAX_SPCV_OUTB_NUM) +#define USI_MAX_MEMCNT (PI + PM8001_MAX_SPCV_OUTB_NUM) +#define PM8001_MAX_DMA_SG SG_ALL enum memory_region_num { AAP1 = 0x0, /* application acceleration processor */ IOP,/* IO processor */ - CI, /* consumer index */ - PI, /* producer index */ - IB, /* inbound queue */ - OB, /* outbound queue */ NVMD, /* NVM device */ DEV_MEM,/* memory for devices */ CCB_MEM,/* memory for command control block */ diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index d04a613..651834c 100755 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -151,10 +151,9 @@ static void read_general_status_table(struct pm8001_hba_info *pm8001_ha) */ static void read_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha) { - int inbQ_num = 1; int i; void __iomem *address = pm8001_ha->inbnd_q_tbl_addr; - for (i = 0; i < inbQ_num; i++) { + for (i = 0; i < PM8001_MAX_INB_NUM; i++) { u32 offset = i * 0x20; pm8001_ha->inbnd_q_tbl[i].pi_pci_bar = get_pci_bar_index(pm8001_mr32(address, (offset + 0x14))); @@ -169,10 +168,9 @@ static void read_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha) */ static void read_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha) { - int outbQ_num = 1; int i; void __iomem *address = pm8001_ha->outbnd_q_tbl_addr; - for (i = 0; i < outbQ_num; i++) { + for (i = 0; i < PM8001_MAX_OUTB_NUM; i++) { u32 offset = i * 0x24; pm8001_ha->outbnd_q_tbl[i].ci_pci_bar = get_pci_bar_index(pm8001_mr32(address, (offset + 0x14))); @@ -225,19 +223,19 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha) pm8001_ha->inbnd_q_tbl[i].element_pri_size_cnt = PM8001_MPI_QUEUE | (64 << 16) | (0x00<<30); pm8001_ha->inbnd_q_tbl[i].upper_base_addr = - pm8001_ha->memoryMap.region[IB].phys_addr_hi; + pm8001_ha->memoryMap.region[IB + i].phys_addr_hi; pm8001_ha->inbnd_q_tbl[i].lower_base_addr = - pm8001_ha->memoryMap.region[IB].phys_addr_lo; + pm8001_ha->memoryMap.region[IB + i].phys_addr_lo; pm8001_ha->inbnd_q_tbl[i].base_virt = - (u8 *)pm8001_ha->memoryMap.region[IB].virt_ptr; + (u8 *)pm8001_ha->memoryMap.region[IB + i].virt_ptr; pm8001_ha->inbnd_q_tbl[i].total_length = - pm8001_ha->memoryMap.region[IB].total_len; + pm8001_ha->memoryMap.region[IB + i].total_len; pm8001_ha->inbnd_q_tbl[i].ci_upper_base_addr= - pm8001_ha->memoryMap.region[CI].phys_addr_hi; + pm8001_ha->memoryMap.region[CI + i].phys_addr_hi; pm8001_ha->inbnd_q_tbl[i].ci_lower_base_addr= - pm8001_ha->memoryMap.region[CI].phys_addr_lo; + pm8001_ha->memoryMap.region[CI + i].phys_addr_lo; pm8001_ha->inbnd_q_tbl[i].ci_virt = - pm8001_ha->memoryMap.region[CI].virt_ptr; + pm8001_ha->memoryMap.region[CI + i].virt_ptr; off
[PATCH 04/15] pm80xx: Structure and variable name update for SPC
>From a08478c7c29817c887469192069dbce8463a5730 Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Mon, 4 Feb 2013 14:26:19 +0530 Subject: [PATCH 04/15] pm80xx: Structure and variable name update for SPC Update of structure and variable names for SPC hardware functionalities. Signed-off-by: Sakthivel K Signed-off-by: Anand Kumar S --- drivers/scsi/pm8001/pm8001_ctl.c | 69 ++--- drivers/scsi/pm8001/pm8001_hwi.c | 210 +++--- 2 files changed, 181 insertions(+), 98 deletions(-) diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c index 45bc197..ae2b124 100755 --- a/drivers/scsi/pm8001/pm8001_ctl.c +++ b/drivers/scsi/pm8001/pm8001_ctl.c @@ -1,5 +1,5 @@ /* - * PMC-Sierra SPC 8001 SAS/SATA based host adapters driver + * PMC-Sierra 8001/8081/8088/8089 SAS/SATA based host adapters driver * * Copyright (c) 2008-2009 USI Co., Ltd. * All rights reserved. @@ -58,8 +58,13 @@ static ssize_t pm8001_ctl_mpi_interface_rev_show(struct device *cdev, struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; - return snprintf(buf, PAGE_SIZE, "%d\n", - pm8001_ha->main_cfg_tbl.interface_rev); + if (pm8001_ha->chip_id == chip_8001) { + return snprintf(buf, PAGE_SIZE, "%d\n", + pm8001_ha->main_cfg_tbl.pm8001_tbl.interface_rev); + } else { + return snprintf(buf, PAGE_SIZE, "%d\n", + pm8001_ha->main_cfg_tbl.pm80xx_tbl.interface_rev); + } } static DEVICE_ATTR(interface_rev, S_IRUGO, pm8001_ctl_mpi_interface_rev_show, NULL); @@ -78,11 +83,19 @@ static ssize_t pm8001_ctl_fw_version_show(struct device *cdev, struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; - return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n", - (u8)(pm8001_ha->main_cfg_tbl.firmware_rev >> 24), - (u8)(pm8001_ha->main_cfg_tbl.firmware_rev >> 16), - (u8)(pm8001_ha->main_cfg_tbl.firmware_rev >> 8), - (u8)(pm8001_ha->main_cfg_tbl.firmware_rev)); + if (pm8001_ha->chip_id == chip_8001) { + return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n", + (u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev >> 24), + (u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev >> 16), + (u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev >> 8), + (u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev)); + } else { + return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n", + (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev >> 24), + (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev >> 16), + (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev >> 8), + (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev)); + } } static DEVICE_ATTR(fw_version, S_IRUGO, pm8001_ctl_fw_version_show, NULL); /** @@ -99,8 +112,13 @@ static ssize_t pm8001_ctl_max_out_io_show(struct device *cdev, struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; - return snprintf(buf, PAGE_SIZE, "%d\n", - pm8001_ha->main_cfg_tbl.max_out_io); + if (pm8001_ha->chip_id == chip_8001) { + return snprintf(buf, PAGE_SIZE, "%d\n", + pm8001_ha->main_cfg_tbl.pm8001_tbl.max_out_io); + } else { + return snprintf(buf, PAGE_SIZE, "%d\n", + pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_out_io); + } } static DEVICE_ATTR(max_out_io, S_IRUGO, pm8001_ctl_max_out_io_show, NULL); /** @@ -117,8 +135,15 @@ static ssize_t pm8001_ctl_max_devices_show(struct device *cdev, struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; - return snprintf(buf, PAGE_SIZE, "%04d\n", - (u16)(pm8001_ha->main_cfg_tbl.max_sgl >> 16)); + if (pm8001_ha->chip_id == chip_8001) { + return snprintf(buf, PAGE_SIZE, "%04d\n", + (u16)(pm8001_ha->main_cfg_tbl.pm8001_tbl.max_sgl >> 16) + ); + } else { + return snprintf(buf, PAGE_SIZE, "%04d\n", + (u16)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_sgl >> 16) + ); + } } static DEVICE_ATTR(max_devices, S_IRUGO, pm8001_ctl_max_devices_show, NULL); /** @@ -136,8 +161,15 @@ static ssize_t pm8001_ctl_max_sg_list_show(struct device *cdev, struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; - return snprintf(buf, PAGE_SIZE, "%04d\n", - pm8001_ha->main_cfg_tbl.max_sgl &
[PATCH 03/15] pm80xx: Added and modified structures, variables and macros for SPCv/ve
>From 5afe6aff983aed38a46bdc9ec26d1035d79d9bb0 Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Mon, 4 Feb 2013 13:46:35 +0530 Subject: [PATCH 03/15] pm80xx: Added and modified structures, variables and macros for SPCv/ve Added SPCv/ve related macros. Updated macros, hba info structure and other structures for SPCv/ve. Signed-off-by: Sakthivel K Signed-off-by: Anand Kumar S --- drivers/scsi/pm8001/pm8001_defs.h | 19 ++-- drivers/scsi/pm8001/pm8001_init.c | 10 - drivers/scsi/pm8001/pm8001_sas.h | 96 - 3 files changed, 108 insertions(+), 17 deletions(-) diff --git a/drivers/scsi/pm8001/pm8001_defs.h b/drivers/scsi/pm8001/pm8001_defs.h index c3d20c8..b25f87c 100755 --- a/drivers/scsi/pm8001/pm8001_defs.h +++ b/drivers/scsi/pm8001/pm8001_defs.h @@ -1,5 +1,5 @@ /* - * PMC-Sierra SPC 8001 SAS/SATA based host adapters driver + * PMC-Sierra 8001/8081/8088/8089 SAS/SATA based host adapters driver * * Copyright (c) 2008-2009 USI Co., Ltd. * All rights reserved. @@ -43,6 +43,10 @@ enum chip_flavors { chip_8001, + chip_8008, + chip_8009, + chip_8018, + chip_8019 }; #define USI_MAX_MEMCNT 9 #define PM8001_MAX_DMA_SG SG_ALL @@ -69,12 +73,19 @@ enum port_type { #define PM8001_MPI_QUEUE 1024 /* maximum mpi queue entries */ #definePM8001_MAX_INB_NUM 1 #definePM8001_MAX_OUTB_NUM 1 +#definePM8001_MAX_SPCV_INB_NUM 1 +#definePM8001_MAX_SPCV_OUTB_NUM4 #definePM8001_CAN_QUEUE 508/* SCSI Queue depth */ +/* Inbound/Outbound queue size */ +#define IOMB_SIZE_SPC 64 +#define IOMB_SIZE_SPCV 128 + /* unchangeable hardware details */ -#definePM8001_MAX_PHYS 8 /* max. possible phys */ -#definePM8001_MAX_PORTS 8 /* max. possible ports */ -#definePM8001_MAX_DEVICES 1024 /* max supported device */ +#definePM8001_MAX_PHYS 16 /* max. possible phys */ +#definePM8001_MAX_PORTS 16 /* max. possible ports */ +#definePM8001_MAX_DEVICES 2048 /* max supported device */ +#definePM8001_MAX_MSIX_VEC 64 /* max msi-x int for spcv/ve */ enum memory_region_num { AAP1 = 0x0, /* application acceleration processor */ diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index 1d883e9..5ce8330 100755 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -44,8 +44,16 @@ static struct scsi_transport_template *pm8001_stt; +/** + * chip info structure to identify chip key functionality as + * encryption available/not, no of ports, hw specific function ref + */ static const struct pm8001_chip_info pm8001_chips[] = { - [chip_8001] = { 8, &pm8001_8001_dispatch,}, + [chip_8001] = {0, 8, &pm8001_8001_dispatch,}, + [chip_8008] = {0, 8, &pm8001_80xx_dispatch,}, + [chip_8009] = {1, 8, &pm8001_80xx_dispatch,}, + [chip_8018] = {0, 16, &pm8001_80xx_dispatch,}, + [chip_8019] = {1, 16, &pm8001_80xx_dispatch,}, }; static int pm8001_id; diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index 1100820..bf4963e 100755 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h @@ -108,6 +108,7 @@ do {\ #define PM8001_NAME_LENGTH 32/* generic length of strings */ extern struct list_head hba_list; extern const struct pm8001_dispatch pm8001_8001_dispatch; +extern const struct pm8001_dispatch pm8001_80xx_dispatch; struct pm8001_hba_info; struct pm8001_ccb_info; @@ -173,6 +174,7 @@ struct pm8001_dispatch { }; struct pm8001_chip_info { + u32 encrypt; u32 n_phy; const struct pm8001_dispatch*dispatch; }; @@ -256,7 +258,20 @@ struct mpi_mem_req { struct mpi_mem region[USI_MAX_MEMCNT]; }; -struct main_cfg_table { +struct encrypt { + u32 cipher_mode; + u32 sec_mode; + u32 status; + u32 flag; +}; + +struct sas_phy_attribute_table { + u32 phystart1_16[16]; + u32 outbound_hw_event_pid1_16[16]; +}; + +union main_cfg_table { + struct { u32 signature; u32 interface_rev; u32 firmware_rev; @@ -292,19 +307,67 @@ struct main_cfg_table { u32 fatal_err_dump_length1; u32 hda_mode_flag; u32 anolog_setup_table_offset; + u32 rsvd[4]; + } pm8001_tbl; + + struct { + u32 signature; + u32 interface_rev; + u32 firmware_rev; + u32 max_out_io; + u32 max_s
[PATCH 02/15] pm80xx: Added vendor and device ids for SPCv/ve controllers
>From edeb2b4b89ff6c7ddbb73366a2b4f6a86815d8eb Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Mon, 4 Feb 2013 12:15:28 +0530 Subject: [PATCH 02/15] pm80xx: Added vendor and device ids for SPCv/SPCve controllers Updated of pci id table with device, vendor, subdevice and subvendor ids for 8081, 8088, 8089 SAS/SATA controllers Signed-off-by: Sakthivel K Signed-off-by: Anand Kumar S --- drivers/scsi/pm8001/pm8001_init.c | 42 1 files changed, 37 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index 3d5e522..1d883e9 100755 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -1,5 +1,5 @@ /* - * PMC-Sierra SPC 8001 SAS/SATA based host adapters driver + * PMC-Sierra PM8001/8081/8088/8089 SAS/SATA based host adapters driver * * Copyright (c) 2008-2009 USI Co., Ltd. * All rights reserved. @@ -843,14 +843,45 @@ err_out_enable: return rc; } +/* update of pci device, vendor id and driver data with + * unique value for each of the controller + */ static struct pci_device_id pm8001_pci_table[] = { - { - PCI_VDEVICE(PMC_Sierra, 0x8001), chip_8001 - }, + { PCI_VDEVICE(PMC_Sierra, 0x8001), chip_8001 }, { PCI_DEVICE(0x117c, 0x0042), .driver_data = chip_8001 }, + /* Support for SPC/SPCv/SPCve controllers */ + { PCI_VDEVICE(ADAPTEC2, 0x8001), chip_8001 }, + { PCI_VDEVICE(PMC_Sierra, 0x8008), chip_8008 }, + { PCI_VDEVICE(ADAPTEC2, 0x8008), chip_8008 }, + { PCI_VDEVICE(PMC_Sierra, 0x8018), chip_8018 }, + { PCI_VDEVICE(ADAPTEC2, 0x8018), chip_8018 }, + { PCI_VDEVICE(PMC_Sierra, 0x8009), chip_8009 }, + { PCI_VDEVICE(ADAPTEC2, 0x8009), chip_8009 }, + { PCI_VDEVICE(PMC_Sierra, 0x8019), chip_8019 }, + { PCI_VDEVICE(ADAPTEC2, 0x8019), chip_8019 }, + { PCI_VENDOR_ID_ADAPTEC2, 0x8081, + PCI_VENDOR_ID_ADAPTEC2, 0x0400, 0, 0, chip_8001 }, + { PCI_VENDOR_ID_ADAPTEC2, 0x8081, + PCI_VENDOR_ID_ADAPTEC2, 0x0800, 0, 0, chip_8001 }, + { PCI_VENDOR_ID_ADAPTEC2, 0x8088, + PCI_VENDOR_ID_ADAPTEC2, 0x0008, 0, 0, chip_8008 }, + { PCI_VENDOR_ID_ADAPTEC2, 0x8088, + PCI_VENDOR_ID_ADAPTEC2, 0x0800, 0, 0, chip_8008 }, + { PCI_VENDOR_ID_ADAPTEC2, 0x8089, + PCI_VENDOR_ID_ADAPTEC2, 0x0008, 0, 0, chip_8009 }, + { PCI_VENDOR_ID_ADAPTEC2, 0x8089, + PCI_VENDOR_ID_ADAPTEC2, 0x0800, 0, 0, chip_8009 }, + { PCI_VENDOR_ID_ADAPTEC2, 0x8088, + PCI_VENDOR_ID_ADAPTEC2, 0x0016, 0, 0, chip_8018 }, + { PCI_VENDOR_ID_ADAPTEC2, 0x8088, + PCI_VENDOR_ID_ADAPTEC2, 0x1600, 0, 0, chip_8018 }, + { PCI_VENDOR_ID_ADAPTEC2, 0x8089, + PCI_VENDOR_ID_ADAPTEC2, 0x0016, 0, 0, chip_8019 }, + { PCI_VENDOR_ID_ADAPTEC2, 0x8089, + PCI_VENDOR_ID_ADAPTEC2, 0x1600, 0, 0, chip_8019 }, {} /* terminate list */ }; @@ -902,7 +933,8 @@ module_init(pm8001_init); module_exit(pm8001_exit); MODULE_AUTHOR("Jack Wang "); -MODULE_DESCRIPTION("PMC-Sierra PM8001 SAS/SATA controller driver"); +MODULE_DESCRIPTION( + "PMC-Sierra PM8001/8081/8088/8089 SAS/SATA controller driver"); MODULE_VERSION(DRV_VERSION); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, pm8001_pci_table); -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 01/15] pm80xx: fix for memory region free
>From 56ee53f01663fa479c0624b81e36545ea5b1ab94 Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Mon, 4 Feb 2013 12:10:02 +0530 Subject: [PATCH 01/15] pm80xx: fix for memory region free All memory regions are allocated based on variables total_len and alignment but free was based on element_size. Signed-off-by: Sakthivel K Signed-off-by: Anand Kumar S --- drivers/scsi/pm8001/pm8001_init.c |3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index 4c9fe73..3d5e522 100755 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -140,7 +140,8 @@ static void pm8001_free(struct pm8001_hba_info *pm8001_ha) for (i = 0; i < USI_MAX_MEMCNT; i++) { if (pm8001_ha->memoryMap.region[i].virt_ptr != NULL) { pci_free_consistent(pm8001_ha->pdev, - pm8001_ha->memoryMap.region[i].element_size, + (pm8001_ha->memoryMap.region[i].total_len + + pm8001_ha->memoryMap.region[i].alignment), pm8001_ha->memoryMap.region[i].virt_ptr, pm8001_ha->memoryMap.region[i].phys_addr); } -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 00/15] Support for PMC 8081/8088/8089 controllers.
James/Linux-scsi, The following patchset provides support for PMC 8081/88/89 series of controllers. >From 9c620d9273640b416054ba76cd267aebaf455ed2 Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Thu, 7 Feb 2013 17:03:42 +0530 Subject: [PATCH 00/15] Support for PMC 8081/8088/8089 controllers. Support for PMC 8081/8088/8089 series of controllers. New data structures and hardware functionality files have been added to support 8088/8089 controllers. The hardware specific file contains new functionality specific to 8088/8089 controllers including support for encryption, thermal settings, FW upgradation. Since 8081/8088/8089 controllers are built on top of 8001 controller most of the data structures and functions of 8001 controller are reused. MSI-X support for 8081/8088/8089 and many more error handling logic to handle controller specific errors have been introduced. Functionality to support multiple inbound and outbound queues have been added for 8088/8089 controllers. Fixes for 8001 driver include memory region fix, NCQ error handling logic, WWN number retrieval for the controller. In addition new memory regions have been introduced for FW flash. Sakthivel K (15): pm80xx: fix for memory region free pm80xx: Added vendor and device ids for SPCv/SPCve controllers pm80xx: Added and modified structures, variables and macros for SPCv/ve pm80xx: Structure and variable name update for SPC pm80xx: Multiple inbound/outbound queue configuration pm80xx: Updated common functions common for SPC and SPCv/ve pm80xx: MSI-X implementation for using 64 interrupts pm80xx: Added SPCv/ve specific hardware functionalities pm80xx: SPCv/ve specific changes in common files pm80xx: SPC new firmware changes for device id 0x8081 alone pm80xx: Firmware flash memory free fix, with addition of new memory region for it pm80xx: Changed module name and debug messages update pm80xx: WWN Modification for PM8081/88/89 controllers pm80xx: NCQ error handling changes pm80xx: thermal, sas controller config and error handling update drivers/scsi/pm8001/Makefile |7 +- drivers/scsi/pm8001/pm8001_ctl.c | 74 +- drivers/scsi/pm8001/pm8001_defs.h | 34 +- drivers/scsi/pm8001/pm8001_hwi.c | 796 +--- drivers/scsi/pm8001/pm8001_hwi.h |4 +- drivers/scsi/pm8001/pm8001_init.c | 1478 +- drivers/scsi/pm8001/pm8001_sas.c | 105 +- drivers/scsi/pm8001/pm8001_sas.h | 176 ++- drivers/scsi/pm8001/pm80xx_hwi.c | 4131 + drivers/scsi/pm8001/pm80xx_hwi.h | 1524 ++ 10 files changed, 7937 insertions(+), 392 deletions(-) create mode 100644 drivers/scsi/pm8001/pm80xx_hwi.c create mode 100644 drivers/scsi/pm8001/pm80xx_hwi.h -Anand -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Test mail
::DISCLAIMER:: The contents of this e-mail and any attachment(s) are confidential and intended for the named recipient(s) only. E-mail transmission is not guaranteed to be secure or error-free as information could be intercepted, corrupted, lost, destroyed, arrive late or incomplete, or may contain viruses in transmission. The e mail and its contents (with or without referred errors) shall therefore not attach any liability on the originator or HCL or its affiliates. Views or opinions, if any, presented in this email are solely those of the author and may not necessarily reflect the views or opinions of HCL or its affiliates. Any form of reproduction, dissemination, copying, disclosure, modification, distribution and / or publication of this message without the prior written consent of authorized representative of HCL is strictly prohibited. If you have received this email in error please delete it and notify the sender immediately. Before opening any email and/or attachments, please check them for viruses and other defects. -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] scsi_debug: Fix endianess in partition table
On Mon, 2013-02-11 at 18:34 +0100, Martin Peschke wrote: > Both start_sect and nr_sects in struct partition are __le32 and > require cpu_to_le32() on assignment. Steffen Maier has pointed me at: block/partitions/msdos.c: return (sector_t)get_unaligned_le32(&p->start_sect); Unfortunately, both get_unaligned_le32() and le32_to_cpu() appear to be in use for start_sect and nr_sects. Any one who would argue for changing my patch from cpu_to_le32 to put_unaligned_le32()? Thanks, Martin > > Without this fix tools like fdisk show an invalid partition table > for SCSI devices emulated by scsi_debug on big-endian architectures, > like s390x. Besides a kernel message like this was emitted: > > sda: p1 start 536870912 is beyond EOD, enabling native capacity > sda: p1 start 536870912 is beyond EOD, truncated > > For verification 'xxd -l 512 /dev/sda' has been used to make sure > that this fix makes scsi_debug generated partition tables on s390x > look like the ones generated on my laptop. > > Signed-off-by: Martin Peschke > Reviewed-by: Steffen Maier > > --- > drivers/scsi/scsi_debug.c |4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > --- a/drivers/scsi/scsi_debug.c > +++ b/drivers/scsi/scsi_debug.c > @@ -2662,8 +2662,8 @@ static void __init sdebug_build_parts(un > / sdebug_sectors_per; > pp->end_sector = (end_sec % sdebug_sectors_per) + 1; > > - pp->start_sect = start_sec; > - pp->nr_sects = end_sec - start_sec + 1; > + pp->start_sect = cpu_to_le32(start_sec); > + pp->nr_sects = cpu_to_le32(end_sec - start_sec + 1); > pp->sys_ind = 0x83; /* plain Linux partition */ > } > } > > > -- > To unsubscribe from this list: send the line "unsubscribe linux-scsi" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html