[PATCH 3/3] ipr: Avoid target_destroy accessing memory after it was freed
Defined target_ids,array_ids and vsets_ids as unsigned long to avoid target_destroy accessing memory after it was freed. Signed-off-by: Wen Xiong --- drivers/scsi/ipr.c | 16 drivers/scsi/ipr.h |6 +++--- 2 files changed, 3 insertions(+), 19 deletions(-) Index: b/drivers/scsi/ipr.c === --- a/drivers/scsi/ipr.c2013-03-14 13:16:03.398966326 -0500 +++ b/drivers/scsi/ipr.c2013-03-14 13:17:04.828022126 -0500 @@ -8972,19 +8972,6 @@ static int ipr_alloc_mem(struct ipr_ioa_ if (!ioa_cfg->res_entries) goto out; - if (ioa_cfg->sis64) { - ioa_cfg->target_ids = kzalloc(sizeof(unsigned long) * - BITS_TO_LONGS(ioa_cfg->max_devs_supported), GFP_KERNEL); - ioa_cfg->array_ids = kzalloc(sizeof(unsigned long) * - BITS_TO_LONGS(ioa_cfg->max_devs_supported), GFP_KERNEL); - ioa_cfg->vset_ids = kzalloc(sizeof(unsigned long) * - BITS_TO_LONGS(ioa_cfg->max_devs_supported), GFP_KERNEL); - - if (!ioa_cfg->target_ids || !ioa_cfg->array_ids - || !ioa_cfg->vset_ids) - goto out_free_res_entries; - } - for (i = 0; i < ioa_cfg->max_devs_supported; i++) { list_add_tail(&ioa_cfg->res_entries[i].queue, &ioa_cfg->free_res_q); ioa_cfg->res_entries[i].ioa_cfg = ioa_cfg; @@ -9081,9 +9068,6 @@ out_free_vpd_cbs: ioa_cfg->vpd_cbs, ioa_cfg->vpd_cbs_dma); out_free_res_entries: kfree(ioa_cfg->res_entries); - kfree(ioa_cfg->target_ids); - kfree(ioa_cfg->array_ids); - kfree(ioa_cfg->vset_ids); goto out; } Index: b/drivers/scsi/ipr.h === --- a/drivers/scsi/ipr.h2013-03-14 11:49:21.408965542 -0500 +++ b/drivers/scsi/ipr.h2013-03-14 13:16:20.131452448 -0500 @@ -1440,9 +1440,9 @@ struct ipr_ioa_cfg { /* * Bitmaps for SIS64 generated target values */ - unsigned long *target_ids; - unsigned long *array_ids; - unsigned long *vset_ids; + unsigned long target_ids[BITS_TO_LONGS(IPR_MAX_SIS64_DEVS)]; + unsigned long array_ids[BITS_TO_LONGS(IPR_MAX_SIS64_DEVS)]; + unsigned long vset_ids[BITS_TO_LONGS(IPR_MAX_SIS64_DEVS)]; u16 type; /* CCIN of the card */ -- -- 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 0/3] Fixed several ipr bugs when bring up an ipr adapter
-- Hi All, These patches fixed several ipr bugs when brining up new adapters. Let me know if you have any questions. Thanks, Wendy -- 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 2/3] ipr: dlpar failed when adding an adapter back
Reinitialize resource queue prior to freeing resource entries to ensure they are not referenced. This fixes an issue with target_destoy accessing memory after it was freed. Signed-off-by: Wen Xiong --- drivers/scsi/ipr.c |1 + 1 file changed, 1 insertion(+) Index: b/drivers/scsi/ipr.c === --- a/drivers/scsi/ipr.c2013-03-14 13:15:46.289276262 -0500 +++ b/drivers/scsi/ipr.c2013-03-14 13:16:03.398966326 -0500 @@ -9728,6 +9728,7 @@ static void __ipr_remove(struct pci_dev spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags); wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); flush_work(&ioa_cfg->work_q); + INIT_LIST_HEAD(&ioa_cfg->used_res_q); spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags); spin_lock(&ipr_driver_lock); -- -- 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 1/3] ipr: fix addition of abort command to HRRQ free queue
From: Kleber Sacilotto de Souza The abort command issued by ipr_cancel_op() is being added to the wrong HRRQ free queue after the command returns. Fix it by using the HRRQ pointer in the ipr command struct itself. Signed-off-by: Kleber Sacilotto de Souza Signed-off-by: Wen Xiong --- drivers/scsi/ipr.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) Index: b/drivers/scsi/ipr.c === --- a/drivers/scsi/ipr.c2013-03-14 11:49:29.819030052 -0500 +++ b/drivers/scsi/ipr.c2013-03-14 13:15:46.289276262 -0500 @@ -5148,7 +5148,7 @@ static int ipr_cancel_op(struct scsi_cmn ipr_trace; } - list_add_tail(&ipr_cmd->queue, &hrrq->hrrq_free_q); + list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); if (!ipr_is_naca_model(res)) res->needs_sync_complete = 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
Re: [PATCH] scsi_transport_fc: Make 'port_state' writeable
Just for my understanding: So this is a bit like writing 0 into the failed attribute of a zfcp_port in sysfs (zfcp_sysfs_port_failed_store()) which forces a port reopen recovery including a sequence of fc_remote_port_delete and fc_remote_port_add? If so, it sounds good to have this functionality for any FC LLD in common code. (And I can think about deprecating parts of zfcp code, next we could consider the same for zfcp's forced LUN and adapter recovery or maybe this already exists as sdev's writable state attribute and the adapter recovery can be performed manually by walking all fc_rports writing their port_state.) On 01/15/2013 04:02 PM, Hannes Reinecke wrote: Multipath might detect a path down even though the LLDD hasn't registered a link down event. This patch makes the 'port_state' FC attribute writeable to enforce a link down scenario in these cases, allowing for a fast failover to the remaining ports. Cc: Chad Dupuis Cc: Andrew Vasquez Cc: James Smart Cc: James Bottomley Cc: Mike Christie Signed-off-by: Hannes Reinecke diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 5e1c6dd..4d28ee5 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -42,6 +42,8 @@ #include "scsi_priv.h" #include "scsi_transport_fc_internal.h" +static void fc_flush_devloss(struct Scsi_Host *shost); +static void fc_flush_work(struct Scsi_Host *shost); static int fc_queue_work(struct Scsi_Host *, struct work_struct *); static void fc_vport_sched_delete(struct work_struct *work); static int fc_vport_setup(struct Scsi_Host *shost, int channel, @@ -949,7 +951,76 @@ show_fc_rport_roles (struct device *dev, struct device_attribute *attr, static FC_DEVICE_ATTR(rport, roles, S_IRUGO, show_fc_rport_roles, NULL); -fc_private_rport_rd_enum_attr(port_state, FC_PORTSTATE_MAX_NAMELEN); +static ssize_t +store_fc_rport_port_state(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned long flags; + struct fc_rport *rport = transport_class_to_rport(dev); + struct Scsi_Host *shost = rport_to_shost(rport); + + spin_lock_irqsave(shost->host_lock, flags); + if (!strncmp(buf, "Blocked", 7)) { + if (rport->port_state != FC_PORTSTATE_ONLINE) { + spin_unlock_irqrestore(shost->host_lock, flags); + return -EBUSY; + } + spin_unlock_irqrestore(shost->host_lock, flags); + fc_remote_port_delete(rport); + } else if (!strncmp(buf, "Online", 6)) { + if (rport->port_state != FC_PORTSTATE_BLOCKED) { + spin_unlock_irqrestore(shost->host_lock, flags); + return -EBUSY; + } + /* Reset back to online for rescan */ + rport->port_state = FC_PORTSTATE_ONLINE; + spin_unlock_irqrestore(shost->host_lock, flags); + + if (!cancel_delayed_work(&rport->fail_io_work)) + fc_flush_devloss(shost); + if (!cancel_delayed_work(&rport->dev_loss_work)) + fc_flush_devloss(shost); + + spin_lock_irqsave(shost->host_lock, flags); + rport->flags &= ~(FC_RPORT_FAST_FAIL_TIMEDOUT | + FC_RPORT_DEVLOSS_PENDING | + FC_RPORT_DEVLOSS_CALLBK_DONE); + spin_unlock_irqrestore(shost->host_lock, flags); + + /* ensure any stgt delete functions are done */ + fc_flush_work(shost); + + if (rport->roles & FC_PORT_ROLE_FCP_TARGET) { + scsi_target_unblock(&rport->dev, SDEV_RUNNING); + /* initiate a scan of the target */ + spin_lock_irqsave(shost->host_lock, flags); + rport->flags |= FC_RPORT_SCAN_PENDING; + scsi_queue_work(shost, &rport->scan_work); + spin_unlock_irqrestore(shost->host_lock, flags); + } + } else + return -EINVAL; + + return count; +} + +static ssize_t +show_fc_rport_port_state (struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fc_rport *rport = transport_class_to_rport(dev); + const char *name; + + name = get_fc_port_state_name(rport->port_state); + if (!name) + return -EINVAL; + return snprintf(buf, FC_PORTSTATE_MAX_NAMELEN, "%s\n", name); +} + +static FC_DEVICE_ATTR(rport, port_state, S_IRUGO | S_IWUSR, + show_fc_rport_port_state, store_fc_rport_port_state); + fc_private_rport_rd_attr(scsi_target_id, "%d\n", 20); /* @@ -2289,7 +2360,7 @@ fc_attach_transport(struct fc_function_template *ft) SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(port_name);
RE: [PATCH v2 net-next 05/22] cxgb4: Add T5 write combining support
> This patch implements a low latency Write Combining (aka Write Coalescing) > work > request path. PCIE maps User Space Doorbell BAR2 region writes to the new > interface to SGE. SGE pulls a new message from PCIE new interface and if its a > coalesced write work request then pushes it for processing. This patch copies > coalesced work request to memory mapped BAR2 space. ... > + } else { > + memset(data, 0, 2 * sizeof(u64)); > + *data += 2; > + } Using memset is overkill (or rather a big overhead if it isn't detected by the compiler). Nothing wrong with: (*data)[0] = 0; (*data)[1] = 0; *data += 2; Actually, typing that, I realise that you should probably have read *data into a local variable, and then updated it when finished. Otherwise some of the accesses might be ones which force the compiler to reload the value. > static inline void ring_tx_db(struct adapter *adap, struct sge_txq *q, int n) > { > + unsigned int *wr, index; > + > wmb();/* write descriptors before telling HW */ > spin_lock(&q->db_lock); > if (!q->db_disabled) { > - t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL), > - QID(q->cntxt_id) | PIDX(n)); > + if (is_t4(adap->chip)) { > + t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL), > + QID(q->cntxt_id) | PIDX(n)); > + } else { > + if (n == 1) { > + index = q->pidx ? (q->pidx - 1) : (q->size - 1); > + wr = (unsigned int *)&q->desc[index]; > + cxgb_pio_copy((u64 __iomem *) > + (adap->bar2 + q->udb + 64), > + (u64 *)wr); Why all the casts on 'wr' ? > + } else > + writel(n, adap->bar2 + q->udb + 8); > + wmb(); Since you actually need memory barriers here on x86 you definitely need a comment saying so, and it would (IMHO) better to use a different define in the source (even if it is currently converted to wmb() in a local header file). Thinking further, for portability you might want to find some way of abstracting the multi-word writes somehow. For example, some of the ppc have a dma engine associated with the PCIe master interface that can be used to generate large TLP. The code would still want to spin waiting for the dma to complete (since the transfer would be far faster than any interrupt path). David -- 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 v2 net-next 00/22] Add support for Chelsio T5 adapter
Acked-by: Steve Wise -- 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 v2 net-next 00/22] Add support for Chelsio T5 adapter
From: Vipul Pandya Date: Thu, 14 Mar 2013 20:38:46 +0530 > We request to merge this patch series via David Miller's net-next tree. We are > copying respective maintainers of all the drivers for reviewing the changes. > Kindly let us know in case of any review comments. All applied to net-next, thanks. -- 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 v2 net-next 01/22] cxgb4: Add register definations for T5
From: Santosh Rastapur Signed-off-by: Santosh Rastapur Signed-off-by: Vipul Pandya --- v2: Replaced #ifdef with portable interface wmb in ring_tx_db drivers/net/ethernet/chelsio/cxgb4/t4_regs.h | 94 ++ 1 files changed, 94 insertions(+), 0 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h index 83ec5f7..22cbcb3 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h @@ -68,9 +68,14 @@ #define QID_SHIFT 15 #define QID(x) ((x) << QID_SHIFT) #define DBPRIO(x) ((x) << 14) +#define DBTYPE(x) ((x) << 13) #define PIDX_MASK 0x3fffU #define PIDX_SHIFT 0 #define PIDX(x) ((x) << PIDX_SHIFT) +#define S_PIDX_T5 0 +#define M_PIDX_T5 0x1fffU +#define PIDX_T5(x) (((x) >> S_PIDX_T5) & M_PIDX_T5) + #define SGE_PF_GTS 0x4 #define INGRESSQID_MASK 0xU @@ -152,6 +157,8 @@ #define QUEUESPERPAGEPF0_MASK 0x000fU #define QUEUESPERPAGEPF0_GET(x) ((x) & QUEUESPERPAGEPF0_MASK) +#define QUEUESPERPAGEPF14 + #define SGE_INT_CAUSE1 0x1024 #define SGE_INT_CAUSE2 0x1030 #define SGE_INT_CAUSE3 0x103c @@ -272,17 +279,36 @@ #define S_HP_INT_THRESH28 #define M_HP_INT_THRESH 0xfU #define V_HP_INT_THRESH(x) ((x) << S_HP_INT_THRESH) +#define S_LP_INT_THRESH_T518 +#define V_LP_INT_THRESH_T5(x) ((x) << S_LP_INT_THRESH_T5) +#define M_LP_COUNT_T50x3U +#define G_LP_COUNT_T5(x) (((x) >> S_LP_COUNT) & M_LP_COUNT_T5) #define M_HP_COUNT 0x7ffU #define S_HP_COUNT 16 #define G_HP_COUNT(x) (((x) >> S_HP_COUNT) & M_HP_COUNT) #define S_LP_INT_THRESH12 #define M_LP_INT_THRESH 0xfU +#define M_LP_INT_THRESH_T50xfffU #define V_LP_INT_THRESH(x) ((x) << S_LP_INT_THRESH) #define M_LP_COUNT 0x7ffU #define S_LP_COUNT 0 #define G_LP_COUNT(x) (((x) >> S_LP_COUNT) & M_LP_COUNT) #define A_SGE_DBFIFO_STATUS 0x10a4 +#define SGE_STAT_TOTAL 0x10e4 +#define SGE_STAT_MATCH 0x10e8 + +#define SGE_STAT_CFG 0x10ec +#define S_STATSOURCE_T59 +#define STATSOURCE_T5(x) ((x) << S_STATSOURCE_T5) + +#define SGE_DBFIFO_STATUS2 0x1118 +#define M_HP_COUNT_T50x3ffU +#define G_HP_COUNT_T5(x) ((x) & M_HP_COUNT_T5) +#define S_HP_INT_THRESH_T510 +#define M_HP_INT_THRESH_T50xfU +#define V_HP_INT_THRESH_T5(x) ((x) << S_HP_INT_THRESH_T5) + #define S_ENABLE_DROP13 #define V_ENABLE_DROP(x) ((x) << S_ENABLE_DROP) #define F_ENABLE_DROPV_ENABLE_DROP(1U) @@ -331,8 +357,27 @@ #define MSIADDRHPERR 0x0002U #define MSIADDRLPERR 0x0001U +#define READRSPERR 0x2000U +#define TRGT1GRPPERR0x1000U +#define IPSOTPERR 0x0800U +#define IPRXDATAGRPPERR 0x0200U +#define IPRXHDRGRPPERR 0x0100U +#define MAGRPPERR 0x0040U +#define VFIDPERR0x0020U +#define HREQWRPERR 0x0001U +#define DREQWRPERR 0x2000U +#define MSTTAGQPERR 0x0400U +#define PIOREQGRPPERR 0x0100U +#define PIOCPLGRPPERR 0x0080U +#define MSIXSTIPERR 0x0004U +#define MSTTIMEOUTPERR 0x0002U +#define MSTGRPPERR 0x0001U + #define PCIE_NONFAT_ERR 0x3010 #define PCIE_MEM_ACCESS_BASE_WIN 0x3068 +#define S_PCIEOFST 10 +#define M_PCIEOFST 0x3fU +#define GET_PCIEOFST(x) (((x) >> S_PCIEOFST) & M_PCIEOFST) #define PCIEOFST_MASK 0xfc00U #define BIR_MASK0x0300U #define BIR_SHIFT 8 @@ -342,6 +387,9 @@ #define WINDOW(x) ((x) << WINDOW_SHIFT) #define PCIE_MEM_ACCESS_OFFSET 0x306c +#define S_PFNUM0 +#define V_PFNUM(x) ((x) << S_PFNUM) + #define PCIE_FW 0x30b8 #define PCIE_FW_ERR 0x8000U #define PCIE_FW_INIT 0x4000U @@ -407,12 +455,18 @@ #define MC_BIST_STATUS_RDATA 0x7688 +#define MA_EDRAM0_BAR 0x77c0 +#define MA_EDRAM1_BAR 0x77c4 +#define EDRAM_SIZE_MASK 0xfffU +#define EDRAM_SIZE_GET(x) ((x) & EDRAM_SIZE_MASK) + #define MA_EXT_MEMORY_BAR 0x77c8 #define EXT_MEM_SIZE_MASK 0x0fffU #define EXT_MEM_SIZE_SHIFT 0 #define EXT_MEM_SIZE_GET(x) (((x) & EXT_MEM_SIZE_MASK) >> EXT_MEM_SIZE_SHIFT) #define MA_TARGET_MEM_ENABLE 0x77d8 +#define EXT_MEM1_ENABLE 0x0010U #define EXT_MEM_ENABLE 0x0004U #define EDRAM1_ENABLE 0x0002U #define EDRAM0_ENABLE 0x0001U @@ -431,6 +485,7 @@ #define MA_PCIE_FW 0x30b8 #define MA_PARITY_ERROR_STATUS 0x77f4 +#define MA_EXT_MEMORY1_BAR 0x7808 #define EDC_0_BASE_ADDR 0x7900 #define EDC_BIST_CMD 0x7904 @@ -801,6 +856,15 @@ #define MPS_PORT_STAT_RX_PORT_PPP7_H 0x60c #define MPS_PORT_STAT_RX_PORT_LESS_64B_L 0x610 #define MPS_PORT_STAT_RX_PORT_LESS_64B_H 0x614 +#define MAC_PORT_CFG2 0x818 +#define MAC_PORT_MAGIC_MACID_LO 0x824 +#define MAC_PORT_MAGIC_MACID_HI 0x828 +#define MAC_PORT_EPIO_DATA0 0x8c0 +#define MAC_PORT_EPIO_DATA1 0x8c4 +#define MAC_PORT_EPIO_DATA2 0x8c8 +#define MAC_PORT_EPIO_DATA3 0x8cc +#define MAC_PORT_EPIO_OP 0x8d0 + #define MPS_CMN_CTL 0x9000 #define NU
[PATCH v2 net-next 05/22] cxgb4: Add T5 write combining support
From: Santosh Rastapur This patch implements a low latency Write Combining (aka Write Coalescing) work request path. PCIE maps User Space Doorbell BAR2 region writes to the new interface to SGE. SGE pulls a new message from PCIE new interface and if its a coalesced write work request then pushes it for processing. This patch copies coalesced work request to memory mapped BAR2 space. Signed-off-by: Santosh Rastapur Signed-off-by: Vipul Pandya --- v2: Replaced #ifdef with portable interface wmb in ring_tx_db drivers/net/ethernet/chelsio/cxgb4/cxgb4.h |2 + drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 53 ++- drivers/net/ethernet/chelsio/cxgb4/sge.c| 52 +- 3 files changed, 102 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index a91dea6..f8ff30e 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -439,6 +439,7 @@ struct sge_txq { spinlock_t db_lock; int db_disabled; unsigned short db_pidx; + u64 udb; }; struct sge_eth_txq {/* state for an SGE Ethernet Tx queue */ @@ -543,6 +544,7 @@ enum chip_type { struct adapter { void __iomem *regs; + void __iomem *bar2; struct pci_dev *pdev; struct device *pdev_dev; unsigned int mbox; diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 3d6d23a..ce1451c 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -1327,6 +1327,8 @@ static char stats_strings[][ETH_GSTRING_LEN] = { "VLANinsertions ", "GROpackets ", "GROmerged ", + "WriteCoalSuccess ", + "WriteCoalFail ", }; static int get_sset_count(struct net_device *dev, int sset) @@ -1422,11 +1424,25 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats, { struct port_info *pi = netdev_priv(dev); struct adapter *adapter = pi->adapter; + u32 val1, val2; t4_get_port_stats(adapter, pi->tx_chan, (struct port_stats *)data); data += sizeof(struct port_stats) / sizeof(u64); collect_sge_port_stats(adapter, pi, (struct queue_port_stats *)data); + data += sizeof(struct queue_port_stats) / sizeof(u64); + if (!is_t4(adapter->chip)) { + t4_write_reg(adapter, SGE_STAT_CFG, STATSOURCE_T5(7)); + val1 = t4_read_reg(adapter, SGE_STAT_TOTAL); + val2 = t4_read_reg(adapter, SGE_STAT_MATCH); + *data = val1 - val2; + data++; + *data = val2; + data++; + } else { + memset(data, 0, 2 * sizeof(u64)); + *data += 2; + } } /* @@ -5337,10 +5353,11 @@ static void free_some_resources(struct adapter *adapter) #define TSO_FLAGS (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN) #define VLAN_FEAT (NETIF_F_SG | NETIF_F_IP_CSUM | TSO_FLAGS | \ NETIF_F_IPV6_CSUM | NETIF_F_HIGHDMA) +#define SEGMENT_SIZE 128 static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - int func, i, err; + int func, i, err, s_qpp, qpp, num_seg; struct port_info *pi; bool highdma = false; struct adapter *adapter = NULL; @@ -5420,7 +5437,34 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) err = t4_prep_adapter(adapter); if (err) - goto out_unmap_bar; + goto out_unmap_bar0; + + if (!is_t4(adapter->chip)) { + s_qpp = QUEUESPERPAGEPF1 * adapter->fn; + qpp = 1 << QUEUESPERPAGEPF0_GET(t4_read_reg(adapter, + SGE_EGRESS_QUEUES_PER_PAGE_PF) >> s_qpp); + num_seg = PAGE_SIZE / SEGMENT_SIZE; + + /* Each segment size is 128B. Write coalescing is enabled only +* when SGE_EGRESS_QUEUES_PER_PAGE_PF reg value for the +* queue is less no of segments that can be accommodated in +* a page size. +*/ + if (qpp > num_seg) { + dev_err(&pdev->dev, + "Incorrect number of egress queues per page\n"); + err = -EINVAL; + goto out_unmap_bar0; + } + adapter->bar2 = ioremap_wc(pci_resource_start(pdev, 2), + pci_resource_len(pdev, 2)); + if (!adapter->bar2) { + dev_err(&pdev->dev, "cannot map device bar2 region\n"); + err = -ENOMEM; + goto out_unmap_bar0; + } + } + setup_memwin(adapter); err = adap_init0(adapter); setup_memwin_rdma(adapter)
[PATCH v2 net-next 22/22] csiostor: Cleanup chip specific operations.
From: Arvind Bhushan This patch removes chip specific operations from the common hardware paths, as well as the Makefile change to accomodate the new files. Signed-off-by: Arvind Bhushan Signed-off-by: Naresh Kumar Inna --- v2: Replaced #ifdef with portable interface wmb in ring_tx_db drivers/scsi/csiostor/Makefile|3 +- drivers/scsi/csiostor/csio_hw.c | 559 - drivers/scsi/csiostor/csio_hw.h | 47 ++-- drivers/scsi/csiostor/csio_init.c | 48 +++- drivers/scsi/csiostor/csio_init.h | 29 +-- drivers/scsi/csiostor/csio_wr.c | 19 +- 6 files changed, 193 insertions(+), 512 deletions(-) diff --git a/drivers/scsi/csiostor/Makefile b/drivers/scsi/csiostor/Makefile index b581966..913b9a9 100644 --- a/drivers/scsi/csiostor/Makefile +++ b/drivers/scsi/csiostor/Makefile @@ -8,4 +8,5 @@ ccflags-y += -I$(srctree)/drivers/net/ethernet/chelsio/cxgb4 obj-$(CONFIG_SCSI_CHELSIO_FCOE) += csiostor.o csiostor-objs := csio_attr.o csio_init.o csio_lnode.o csio_scsi.o \ - csio_hw.o csio_isr.o csio_mb.o csio_rnode.o csio_wr.o + csio_hw.o csio_hw_t4.o csio_hw_t5.o csio_isr.o \ + csio_mb.o csio_rnode.o csio_wr.o diff --git a/drivers/scsi/csiostor/csio_hw.c b/drivers/scsi/csiostor/csio_hw.c index bdd78fb..a0b4c89 100644 --- a/drivers/scsi/csiostor/csio_hw.c +++ b/drivers/scsi/csiostor/csio_hw.c @@ -61,7 +61,7 @@ int csio_msi = 2; static int dev_num; /* FCoE Adapter types & its description */ -static const struct csio_adap_desc csio_fcoe_adapters[] = { +static const struct csio_adap_desc csio_t4_fcoe_adapters[] = { {"T440-Dbg 10G", "Chelsio T440-Dbg 10G [FCoE]"}, {"T420-CR 10G", "Chelsio T420-CR 10G [FCoE]"}, {"T422-CR 10G/1G", "Chelsio T422-CR 10G/1G [FCoE]"}, @@ -77,7 +77,38 @@ static const struct csio_adap_desc csio_fcoe_adapters[] = { {"B404-BT 1G", "Chelsio B404-BT 1G [FCoE]"}, {"T480-CR 10G", "Chelsio T480-CR 10G [FCoE]"}, {"T440-LP-CR 10G", "Chelsio T440-LP-CR 10G [FCoE]"}, - {"T4 FPGA", "Chelsio T4 FPGA [FCoE]"} + {"AMSTERDAM 10G", "Chelsio AMSTERDAM 10G [FCoE]"}, + {"HUAWEI T480 10G", "Chelsio HUAWEI T480 10G [FCoE]"}, + {"HUAWEI T440 10G", "Chelsio HUAWEI T440 10G [FCoE]"}, + {"HUAWEI STG 10G", "Chelsio HUAWEI STG 10G [FCoE]"}, + {"ACROMAG XAUI 10G", "Chelsio ACROMAG XAUI 10G [FCoE]"}, + {"ACROMAG SFP+ 10G", "Chelsio ACROMAG SFP+ 10G [FCoE]"}, + {"QUANTA SFP+ 10G", "Chelsio QUANTA SFP+ 10G [FCoE]"}, + {"HUAWEI 10Gbase-T", "Chelsio HUAWEI 10Gbase-T [FCoE]"}, + {"HUAWEI T4TOE 10G", "Chelsio HUAWEI T4TOE 10G [FCoE]"} +}; + +static const struct csio_adap_desc csio_t5_fcoe_adapters[] = { + {"T580-Dbg 10G", "Chelsio T580-Dbg 10G [FCoE]"}, + {"T520-CR 10G", "Chelsio T520-CR 10G [FCoE]"}, + {"T522-CR 10G/1G", "Chelsio T452-CR 10G/1G [FCoE]"}, + {"T540-CR 10G", "Chelsio T540-CR 10G [FCoE]"}, + {"T520-BCH 10G", "Chelsio T520-BCH 10G [FCoE]"}, + {"T540-BCH 10G", "Chelsio T540-BCH 10G [FCoE]"}, + {"T540-CH 10G", "Chelsio T540-CH 10G [FCoE]"}, + {"T520-SO 10G", "Chelsio T520-SO 10G [FCoE]"}, + {"T520-CX4 10G", "Chelsio T520-CX4 10G [FCoE]"}, + {"T520-BT 10G", "Chelsio T520-BT 10G [FCoE]"}, + {"T504-BT 1G", "Chelsio T504-BT 1G [FCoE]"}, + {"B520-SR 10G", "Chelsio B520-SR 10G [FCoE]"}, + {"B504-BT 1G", "Chelsio B504-BT 1G [FCoE]"}, + {"T580-CR 10G", "Chelsio T580-CR 10G [FCoE]"}, + {"T540-LP-CR 10G", "Chelsio T540-LP-CR 10G [FCoE]"}, + {"AMSTERDAM 10G", "Chelsio AMSTERDAM 10G [FCoE]"}, + {"T580-LP-CR 40G", "Chelsio T580-LP-CR 40G [FCoE]"}, + {"T520-LL-CR 10G", "Chelsio T520-LL-CR 10G [FCoE]"}, + {"T560-CR 40G", "Chelsio T560-CR 40G [FCoE]"}, + {"T580-CR 40G", "Chelsio T580-CR 40G [FCoE]"} }; static void csio_mgmtm_cleanup(struct csio_mgmtm *); @@ -124,7 +155,7 @@ int csio_is_hw_removing(struct csio_hw *hw) * at the time it indicated completion is stored there. Returns 0 if the * operation completes and -EAGAIN otherwise. */ -static int +int csio_hw_wait_op_done_val(struct csio_hw *hw, int reg, uint32_t mask, int polarity, int attempts, int delay, uint32_t *valp) { @@ -145,6 +176,24 @@ csio_hw_wait_op_done_val(struct csio_hw *hw, int reg, uint32_t mask, } } +/* + * csio_hw_tp_wr_bits_indirect - set/clear bits in an indirect TP register + * @hw: the adapter + * @addr: the indirect TP register address + * @mask: specifies the field within the register to modify + * @val: new value for the field + * + * Sets a field of an indirect TP register to the given value. + */ +void +csio_hw_tp_wr_bits_indirect(struct csio_hw *hw, unsigned int addr, + unsigned int mask, unsigned int val) +{ + csio_wr_reg32(hw, addr, TP_PIO_ADDR); + val |= csio_rd_reg32(hw, TP_PIO_DATA) & ~mask; + csio_wr_reg32(
[PATCH v2 net-next 21/22] csiostor: Header file modifications for chip support and bug fixes.
From: Arvind Bhushan This patch defines the common operations to support multiple chips. It includes common header file modifications to support the current chips (T4 and T5). It also includes the following bug fixes: - reconfirms the rnode state after an implicit logo. - corrects the stats array size. - sets up and checks flags correctly when coming up as master and finding the card initialized Reported-by: Dan Carpenter Signed-off-by: Arvind Bhushan Signed-off-by: Naresh Kumar Inna --- v2: Replaced #ifdef with portable interface wmb in ring_tx_db drivers/scsi/csiostor/csio_hw_chip.h | 175 ++ drivers/scsi/csiostor/csio_lnode.h |2 +- drivers/scsi/csiostor/csio_rnode.c | 10 ++- drivers/scsi/csiostor/csio_rnode.h |2 +- drivers/scsi/csiostor/csio_wr.c | 41 +--- 5 files changed, 212 insertions(+), 18 deletions(-) create mode 100644 drivers/scsi/csiostor/csio_hw_chip.h diff --git a/drivers/scsi/csiostor/csio_hw_chip.h b/drivers/scsi/csiostor/csio_hw_chip.h new file mode 100644 index 000..bca0de6 --- /dev/null +++ b/drivers/scsi/csiostor/csio_hw_chip.h @@ -0,0 +1,175 @@ +/* + * This file is part of the Chelsio FCoE driver for Linux. + * + * Copyright (c) 2008-2013 Chelsio Communications, Inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + *copyright notice, this list of conditions and the following + *disclaimer. + * + * - Redistributions in binary form must reproduce the above + *copyright notice, this list of conditions and the following + *disclaimer in the documentation and/or other materials + *provided with the distribution. + * + * 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. + */ + +#ifndef __CSIO_HW_CHIP_H__ +#define __CSIO_HW_CHIP_H__ + +#include "csio_defs.h" + +/* FCoE device IDs for T4 */ +#define CSIO_DEVID_T440DBG_FCOE0x4600 +#define CSIO_DEVID_T420CR_FCOE 0x4601 +#define CSIO_DEVID_T422CR_FCOE 0x4602 +#define CSIO_DEVID_T440CR_FCOE 0x4603 +#define CSIO_DEVID_T420BCH_FCOE0x4604 +#define CSIO_DEVID_T440BCH_FCOE0x4605 +#define CSIO_DEVID_T440CH_FCOE 0x4606 +#define CSIO_DEVID_T420SO_FCOE 0x4607 +#define CSIO_DEVID_T420CX_FCOE 0x4608 +#define CSIO_DEVID_T420BT_FCOE 0x4609 +#define CSIO_DEVID_T404BT_FCOE 0x460A +#define CSIO_DEVID_B420_FCOE 0x460B +#define CSIO_DEVID_B404_FCOE 0x460C +#define CSIO_DEVID_T480CR_FCOE 0x460D +#define CSIO_DEVID_T440LPCR_FCOE 0x460E +#define CSIO_DEVID_AMSTERDAM_T4_FCOE 0x460F +#define CSIO_DEVID_HUAWEI_T480_FCOE0x4680 +#define CSIO_DEVID_HUAWEI_T440_FCOE0x4681 +#define CSIO_DEVID_HUAWEI_STG310_FCOE 0x4682 +#define CSIO_DEVID_ACROMAG_XMC_XAUI0x4683 +#define CSIO_DEVID_ACROMAG_XMC_SFP_FCOE0x4684 +#define CSIO_DEVID_QUANTA_MEZZ_SFP_FCOE0x4685 +#define CSIO_DEVID_HUAWEI_10GT_FCOE0x4686 +#define CSIO_DEVID_HUAWEI_T440_TOE_FCOE0x4687 + +/* FCoE device IDs for T5 */ +#define CSIO_DEVID_T580DBG_FCOE0x5600 +#define CSIO_DEVID_T520CR_FCOE 0x5601 +#define CSIO_DEVID_T522CR_FCOE 0x5602 +#define CSIO_DEVID_T540CR_FCOE 0x5603 +#define CSIO_DEVID_T520BCH_FCOE0x5604 +#define CSIO_DEVID_T540BCH_FCOE0x5605 +#define CSIO_DEVID_T540CH_FCOE 0x5606 +#define CSIO_DEVID_T520SO_FCOE 0x5607 +#define CSIO_DEVID_T520CX_FCOE 0x5608 +#define CSIO_DEVID_T520BT_FCOE 0x5609 +#define CSIO_DEVID_T504BT_FCOE 0x560A +#define CSIO_DEVID_B520_FCOE 0x560B +#define CSIO_DEVID_B504_FCOE 0x560C +#define CSIO_DEVID_T580CR2_FCOE0x560D +#define CSIO_DEVID_T540LPCR_FCOE
[PATCH v2 net-next 20/22] csiostor: Add T5 adapter operations.
From: Arvind Bhushan This patch creates a new file for T5 adapter operations. Signed-off-by: Arvind Bhushan Signed-off-by: Naresh Kumar Inna --- v2: Replaced #ifdef with portable interface wmb in ring_tx_db drivers/scsi/csiostor/csio_hw_t5.c | 397 1 files changed, 397 insertions(+), 0 deletions(-) create mode 100644 drivers/scsi/csiostor/csio_hw_t5.c diff --git a/drivers/scsi/csiostor/csio_hw_t5.c b/drivers/scsi/csiostor/csio_hw_t5.c new file mode 100644 index 000..27745c1 --- /dev/null +++ b/drivers/scsi/csiostor/csio_hw_t5.c @@ -0,0 +1,397 @@ +/* + * This file is part of the Chelsio FCoE driver for Linux. + * + * Copyright (c) 2008-2013 Chelsio Communications, Inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + *copyright notice, this list of conditions and the following + *disclaimer. + * + * - Redistributions in binary form must reproduce the above + *copyright notice, this list of conditions and the following + *disclaimer in the documentation and/or other materials + *provided with the distribution. + * + * 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 "csio_hw.h" +#include "csio_init.h" + +static int +csio_t5_set_mem_win(struct csio_hw *hw, uint32_t win) +{ + u32 mem_win_base; + /* +* Truncation intentional: we only read the bottom 32-bits of the +* 64-bit BAR0/BAR1 ... We use the hardware backdoor mechanism to +* read BAR0 instead of using pci_resource_start() because we could be +* operating from within a Virtual Machine which is trapping our +* accesses to our Configuration Space and we need to set up the PCI-E +* Memory Window decoders with the actual addresses which will be +* coming across the PCI-E link. +*/ + + /* For T5, only relative offset inside the PCIe BAR is passed */ + mem_win_base = MEMWIN_BASE; + + /* +* Set up memory window for accessing adapter memory ranges. (Read +* back MA register to ensure that changes propagate before we attempt +* to use the new values.) +*/ + csio_wr_reg32(hw, mem_win_base | BIR(0) | + WINDOW(ilog2(MEMWIN_APERTURE) - 10), + PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, win)); + csio_rd_reg32(hw, + PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, win)); + + return 0; +} + +/* + * Interrupt handler for the PCIE module. + */ +static void +csio_t5_pcie_intr_handler(struct csio_hw *hw) +{ + static struct intr_info sysbus_intr_info[] = { + { RNPP, "RXNP array parity error", -1, 1 }, + { RPCP, "RXPC array parity error", -1, 1 }, + { RCIP, "RXCIF array parity error", -1, 1 }, + { RCCP, "Rx completions control array parity error", -1, 1 }, + { RFTP, "RXFT array parity error", -1, 1 }, + { 0, NULL, 0, 0 } + }; + static struct intr_info pcie_port_intr_info[] = { + { TPCP, "TXPC array parity error", -1, 1 }, + { TNPP, "TXNP array parity error", -1, 1 }, + { TFTP, "TXFT array parity error", -1, 1 }, + { TCAP, "TXCA array parity error", -1, 1 }, + { TCIP, "TXCIF array parity error", -1, 1 }, + { RCAP, "RXCA array parity error", -1, 1 }, + { OTDD, "outbound request TLP discarded", -1, 1 }, + { RDPE, "Rx data parity error", -1, 1 }, + { TDUE, "Tx uncorrectable data error", -1, 1 }, + { 0, NULL, 0, 0 } + }; + + static struct intr_info pcie_intr_info[] = { + { MSTGRPPERR, "Master Response Read Queue parity error", + -1, 1 }, + { MSTTIMEOUTPERR, "Master Timeout FIFO parity error", -1, 1 }, + { MSIXSTIPERR, "MSI-X STI SRAM parity error", -1, 1 }, + { MSIXADDRLPERR, "MSI-X AddrL parity error", -1, 1 }, + { MSIXADDRHPERR, "MSI-X AddrH parit
[PATCH v2 net-next 19/22] csiostor: Segregate T4 adapter operations.
From: Arvind Bhushan This patch separates T4 adapter operations into a new file. Signed-off-by: Arvind Bhushan Signed-off-by: Naresh Kumar Inna --- v2: Replaced #ifdef with portable interface wmb in ring_tx_db drivers/scsi/csiostor/csio_hw_t4.c | 403 1 files changed, 403 insertions(+), 0 deletions(-) create mode 100644 drivers/scsi/csiostor/csio_hw_t4.c diff --git a/drivers/scsi/csiostor/csio_hw_t4.c b/drivers/scsi/csiostor/csio_hw_t4.c new file mode 100644 index 000..89ecbac --- /dev/null +++ b/drivers/scsi/csiostor/csio_hw_t4.c @@ -0,0 +1,403 @@ +/* + * This file is part of the Chelsio FCoE driver for Linux. + * + * Copyright (c) 2008-2013 Chelsio Communications, Inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + *copyright notice, this list of conditions and the following + * - Redistributions in binary form must reproduce the above + *copyright notice, this list of conditions and the following + *disclaimer in the documentation and/or other materials + *provided with the distribution. + * + * 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 "csio_hw.h" +#include "csio_init.h" + +/* + * Return the specified PCI-E Configuration Space register from our Physical + * Function. We try first via a Firmware LDST Command since we prefer to let + * the firmware own all of these registers, but if that fails we go for it + * directly ourselves. + */ +static uint32_t +csio_t4_read_pcie_cfg4(struct csio_hw *hw, int reg) +{ + u32 val = 0; + struct csio_mb *mbp; + int rv; + struct fw_ldst_cmd *ldst_cmd; + + mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC); + if (!mbp) { + CSIO_INC_STATS(hw, n_err_nomem); + pci_read_config_dword(hw->pdev, reg, &val); + return val; + } + + csio_mb_ldst(hw, mbp, CSIO_MB_DEFAULT_TMO, reg); + rv = csio_mb_issue(hw, mbp); + + /* +* If the LDST Command suucceeded, exctract the returned register +* value. Otherwise read it directly ourself. +*/ + if (rv == 0) { + ldst_cmd = (struct fw_ldst_cmd *)(mbp->mb); + val = ntohl(ldst_cmd->u.pcie.data[0]); + } else + pci_read_config_dword(hw->pdev, reg, &val); + + mempool_free(mbp, hw->mb_mempool); + + return val; +} + +static int +csio_t4_set_mem_win(struct csio_hw *hw, uint32_t win) +{ + u32 bar0; + u32 mem_win_base; + + /* +* Truncation intentional: we only read the bottom 32-bits of the +* 64-bit BAR0/BAR1 ... We use the hardware backdoor mechanism to +* read BAR0 instead of using pci_resource_start() because we could be +* operating from within a Virtual Machine which is trapping our +* accesses to our Configuration Space and we need to set up the PCI-E +* Memory Window decoders with the actual addresses which will be +* coming across the PCI-E link. +*/ + bar0 = csio_t4_read_pcie_cfg4(hw, PCI_BASE_ADDRESS_0); + bar0 &= PCI_BASE_ADDRESS_MEM_MASK; + + mem_win_base = bar0 + MEMWIN_BASE; + + /* +* Set up memory window for accessing adapter memory ranges. (Read +* back MA register to ensure that changes propagate before we attempt +* to use the new values.) +*/ + csio_wr_reg32(hw, mem_win_base | BIR(0) | + WINDOW(ilog2(MEMWIN_APERTURE) - 10), + PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, win)); + csio_rd_reg32(hw, + PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, win)); + return 0; +} + +/* + * Interrupt handler for the PCIE module. + */ +static void +csio_t4_pcie_intr_handler(struct csio_hw *hw) +{ + static struct intr_info sysbus_intr_info[] = { + { RNPP, "RXNP array parity error", -1, 1 }, + { RPCP, "RXPC array parity error", -1, 1 }, + { RCIP, "RXCIF array parity error", -1, 1 }, + { RCC
[PATCH v2 net-next 18/22] RDMA/cxgb4: Fix onchip queue support for T5
T5 adapter does not support onchip queue memory. Present logic fails to allocate QP for T5 and returns an error. Also, if module parameter ocqp_support is zero then we are unable to allocate QP which should not be the case. Ideally if ocqp_support parameter is 0 or onchip queue support is disable then host QP should be allocated before returning an error. Signed-off-by: Vipul Pandya --- v2: Replaced #ifdef with portable interface wmb in ring_tx_db drivers/infiniband/hw/cxgb4/qp.c | 13 + 1 files changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c index 90833d7..9fe6f1e 100644 --- a/drivers/infiniband/hw/cxgb4/qp.c +++ b/drivers/infiniband/hw/cxgb4/qp.c @@ -140,7 +140,7 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq, int wr_len; struct c4iw_wr_wait wr_wait; struct sk_buff *skb; - int ret; + int ret = 0; int eqsize; wq->sq.qid = c4iw_get_qpid(rdev, uctx); @@ -180,17 +180,14 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq, } if (user) { - ret = alloc_oc_sq(rdev, &wq->sq); - if (ret) + if (alloc_oc_sq(rdev, &wq->sq) && alloc_host_sq(rdev, &wq->sq)) goto free_hwaddr; - - ret = alloc_host_sq(rdev, &wq->sq); - if (ret) - goto free_sq; - } else + } else { ret = alloc_host_sq(rdev, &wq->sq); if (ret) goto free_hwaddr; + } + memset(wq->sq.queue, 0, wq->sq.memsize); dma_unmap_addr_set(&wq->sq, mapping, wq->sq.dma_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 v2 net-next 17/22] RDMA/cxgb4: Bump tcam_full stat and WR reply timeout
Always bump the tcam_full stat. Also, bump wr reply timeout to 30 seconds. Signed-off-by: Vipul Pandya --- v2: Replaced #ifdef with portable interface wmb in ring_tx_db drivers/infiniband/hw/cxgb4/cm.c |2 +- drivers/infiniband/hw/cxgb4/iw_cxgb4.h |2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 272bf78..8dcc84f 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -1693,9 +1693,9 @@ static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb) case CPL_ERR_CONN_TIMEDOUT: break; case CPL_ERR_TCAM_FULL: + dev->rdev.stats.tcam_full++; if (dev->rdev.lldi.enable_fw_ofld_conn) { mutex_lock(&dev->rdev.stats.lock); - dev->rdev.stats.tcam_full++; mutex_unlock(&dev->rdev.stats.lock); send_fw_act_open_req(ep, GET_TID_TID(GET_AOPEN_ATID( diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h index 08e406c..485183a 100644 --- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h +++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h @@ -162,7 +162,7 @@ static inline int c4iw_num_stags(struct c4iw_rdev *rdev) return min((int)T4_MAX_NUM_STAG, (int)(rdev->lldi.vr->stag.size >> 5)); } -#define C4IW_WR_TO (10*HZ) +#define C4IW_WR_TO (30*HZ) struct c4iw_wr_wait { struct completion completion; -- 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 v2 net-next 15/22] RDMA/cxgb4: Use DSGLs for fastreg and adapter memory writes for T5.
It enables direct DMA by HW to memory region PBL arrays and fast register PBL arrays from host memory, vs the T4 way of passing these arrays in the WR itself. The result is lower latency for memory registration, and larger PBL array support for fast register operations. This patch also updates ULP_TX_MEM_WRITE command fields for T5. Ordering bit of ULP_TX_MEM_WRITE is at bit position 22 in T5 and at 23 in T4. Signed-off-by: Vipul Pandya --- v2: Replaced #ifdef with portable interface wmb in ring_tx_db drivers/infiniband/hw/cxgb4/iw_cxgb4.h |2 +- drivers/infiniband/hw/cxgb4/mem.c | 138 -- drivers/infiniband/hw/cxgb4/qp.c| 76 ++- drivers/infiniband/hw/cxgb4/t4.h|2 +- drivers/net/ethernet/chelsio/cxgb4/t4_msg.h |8 ++ 5 files changed, 190 insertions(+), 36 deletions(-) diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h index 4dbe96a..08e406c 100644 --- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h +++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h @@ -369,7 +369,6 @@ struct c4iw_fr_page_list { DEFINE_DMA_UNMAP_ADDR(mapping); dma_addr_t dma_addr; struct c4iw_dev *dev; - int size; }; static inline struct c4iw_fr_page_list *to_c4iw_fr_page_list( @@ -940,6 +939,7 @@ extern c4iw_handler_func c4iw_handlers[NUM_CPL_CMDS]; extern int c4iw_max_read_depth; extern int db_fc_threshold; extern int db_coalescing_threshold; +extern int use_dsgl; #endif diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c index 903a92d..33db9ee 100644 --- a/drivers/infiniband/hw/cxgb4/mem.c +++ b/drivers/infiniband/hw/cxgb4/mem.c @@ -30,16 +30,76 @@ * SOFTWARE. */ +#include +#include #include #include #include "iw_cxgb4.h" +int use_dsgl = 1; +module_param(use_dsgl, int, 0644); +MODULE_PARM_DESC(use_dsgl, "Use DSGL for PBL/FastReg (default=1)"); + #define T4_ULPTX_MIN_IO 32 #define C4IW_MAX_INLINE_SIZE 96 +#define T4_ULPTX_MAX_DMA 1024 +#define C4IW_INLINE_THRESHOLD 128 -static int write_adapter_mem(struct c4iw_rdev *rdev, u32 addr, u32 len, -void *data) +static int inline_threshold = C4IW_INLINE_THRESHOLD; +module_param(inline_threshold, int, 0644); +MODULE_PARM_DESC(inline_threshold, "inline vs dsgl threshold (default=128)"); + +static int _c4iw_write_mem_dma_aligned(struct c4iw_rdev *rdev, u32 addr, + u32 len, void *data, int wait) +{ + struct sk_buff *skb; + struct ulp_mem_io *req; + struct ulptx_sgl *sgl; + u8 wr_len; + int ret = 0; + struct c4iw_wr_wait wr_wait; + + addr &= 0x7FF; + + if (wait) + c4iw_init_wr_wait(&wr_wait); + wr_len = roundup(sizeof(*req) + sizeof(*sgl), 16); + + skb = alloc_skb(wr_len, GFP_KERNEL | __GFP_NOFAIL); + if (!skb) + return -ENOMEM; + set_wr_txq(skb, CPL_PRIORITY_CONTROL, 0); + + req = (struct ulp_mem_io *)__skb_put(skb, wr_len); + memset(req, 0, wr_len); + INIT_ULPTX_WR(req, wr_len, 0, 0); + req->wr.wr_hi = cpu_to_be32(FW_WR_OP(FW_ULPTX_WR) | + (wait ? FW_WR_COMPL(1) : 0)); + req->wr.wr_lo = wait ? (__force __be64)&wr_wait : 0; + req->wr.wr_mid = cpu_to_be32(FW_WR_LEN16(DIV_ROUND_UP(wr_len, 16))); + req->cmd = cpu_to_be32(ULPTX_CMD(ULP_TX_MEM_WRITE)); + req->cmd |= cpu_to_be32(V_T5_ULP_MEMIO_ORDER(1)); + req->dlen = cpu_to_be32(ULP_MEMIO_DATA_LEN(len>>5)); + req->len16 = cpu_to_be32(DIV_ROUND_UP(wr_len-sizeof(req->wr), 16)); + req->lock_addr = cpu_to_be32(ULP_MEMIO_ADDR(addr)); + + sgl = (struct ulptx_sgl *)(req + 1); + sgl->cmd_nsge = cpu_to_be32(ULPTX_CMD(ULP_TX_SC_DSGL) | + ULPTX_NSGE(1)); + sgl->len0 = cpu_to_be32(len); + sgl->addr0 = cpu_to_be64(virt_to_phys(data)); + + ret = c4iw_ofld_send(rdev, skb); + if (ret) + return ret; + if (wait) + ret = c4iw_wait_for_reply(rdev, &wr_wait, 0, 0, __func__); + return ret; +} + +static int _c4iw_write_mem_inline(struct c4iw_rdev *rdev, u32 addr, u32 len, + void *data) { struct sk_buff *skb; struct ulp_mem_io *req; @@ -47,6 +107,12 @@ static int write_adapter_mem(struct c4iw_rdev *rdev, u32 addr, u32 len, u8 wr_len, *to_dp, *from_dp; int copy_len, num_wqe, i, ret = 0; struct c4iw_wr_wait wr_wait; + __be32 cmd = cpu_to_be32(ULPTX_CMD(ULP_TX_MEM_WRITE)); + + if (is_t4(rdev->lldi.adapter_type)) + cmd |= cpu_to_be32(ULP_MEMIO_ORDER(1)); + else + cmd |= cpu_to_be32(V_T5_ULP_MEMIO_IMM(1)); addr &= 0x7FF; PDBG("%s addr 0x%x len %u\n", __func__, addr, len); @@ -77,7 +143,7 @@ static int write_adapter_mem(struct c4iw_rdev *rdev, u32 addr, u32 len,
[PATCH v2 net-next 13/22] RDMA/cxgb4: Turn off db coalescing when RDMA QPs are in use.
Signed-off-by: Vipul Pandya --- v2: Replaced #ifdef with portable interface wmb in ring_tx_db drivers/infiniband/hw/cxgb4/qp.c| 20 drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 19 +++ drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h |3 +++ drivers/net/ethernet/chelsio/cxgb4/t4_regs.h|4 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c index c460244..da4869f 100644 --- a/drivers/infiniband/hw/cxgb4/qp.c +++ b/drivers/infiniband/hw/cxgb4/qp.c @@ -42,10 +42,17 @@ static int ocqp_support = 1; module_param(ocqp_support, int, 0644); MODULE_PARM_DESC(ocqp_support, "Support on-chip SQs (default=1)"); -int db_fc_threshold = 2000; +int db_fc_threshold = 1000; module_param(db_fc_threshold, int, 0644); -MODULE_PARM_DESC(db_fc_threshold, "QP count/threshold that triggers automatic " -"db flow control mode (default = 2000)"); +MODULE_PARM_DESC(db_fc_threshold, +"QP count/threshold that triggers" +" automatic db flow control mode (default = 1000)"); + +int db_coalescing_threshold; +module_param(db_coalescing_threshold, int, 0644); +MODULE_PARM_DESC(db_coalescing_threshold, +"QP count/threshold that triggers" +" disabling db coalescing (default = 0)"); static void set_state(struct c4iw_qp *qhp, enum c4iw_qp_state state) { @@ -1448,6 +1455,8 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp) rhp->db_state = NORMAL; idr_for_each(&rhp->qpidr, enable_qp_db, NULL); } + if (rhp->qpcnt <= db_coalescing_threshold) + cxgb4_enable_db_coalescing(rhp->rdev.lldi.ports[0]); spin_unlock_irq(&rhp->lock); atomic_dec(&qhp->refcnt); wait_event(qhp->wait, !atomic_read(&qhp->refcnt)); @@ -1559,11 +1568,14 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs, spin_lock_irq(&rhp->lock); if (rhp->db_state != NORMAL) t4_disable_wq_db(&qhp->wq); - if (++rhp->qpcnt > db_fc_threshold && rhp->db_state == NORMAL) { + rhp->qpcnt++; + if (rhp->qpcnt > db_fc_threshold && rhp->db_state == NORMAL) { rhp->rdev.stats.db_state_transitions++; rhp->db_state = FLOW_CONTROL; idr_for_each(&rhp->qpidr, disable_qp_db, NULL); } + if (rhp->qpcnt > db_coalescing_threshold) + cxgb4_disable_db_coalescing(rhp->rdev.lldi.ports[0]); ret = insert_handle_nolock(rhp, &rhp->qpidr, qhp, qhp->wq.sq.qid); spin_unlock_irq(&rhp->lock); if (ret) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index a59bb23..e76cf03 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -3397,6 +3397,25 @@ out: } EXPORT_SYMBOL(cxgb4_sync_txq_pidx); +void cxgb4_disable_db_coalescing(struct net_device *dev) +{ + struct adapter *adap; + + adap = netdev2adap(dev); + t4_set_reg_field(adap, A_SGE_DOORBELL_CONTROL, F_NOCOALESCE, +F_NOCOALESCE); +} +EXPORT_SYMBOL(cxgb4_disable_db_coalescing); + +void cxgb4_enable_db_coalescing(struct net_device *dev) +{ + struct adapter *adap; + + adap = netdev2adap(dev); + t4_set_reg_field(adap, A_SGE_DOORBELL_CONTROL, F_NOCOALESCE, 0); +} +EXPORT_SYMBOL(cxgb4_enable_db_coalescing); + static struct pci_driver cxgb4_driver; static void check_neigh_update(struct neighbour *neigh) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h index e2bbc7f..4faf4d0 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h @@ -269,4 +269,7 @@ struct sk_buff *cxgb4_pktgl_to_skb(const struct pkt_gl *gl, unsigned int skb_len, unsigned int pull_len); int cxgb4_sync_txq_pidx(struct net_device *dev, u16 qid, u16 pidx, u16 size); int cxgb4_flush_eq_cache(struct net_device *dev); +void cxgb4_disable_db_coalescing(struct net_device *dev); +void cxgb4_enable_db_coalescing(struct net_device *dev); + #endif /* !__CXGB4_OFLD_H */ diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h index 22cbcb3..ef146c0 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h @@ -241,6 +241,10 @@ #define SGE_DOORBELL_CONTROL 0x10a8 #define ENABLE_DROP(1 << 13) +#define S_NOCOALESCE26 +#define V_NOCOALESCE(x) ((x) << S_NOCOALESCE) +#define F_NOCOALESCEV_NOCOALESCE(1U) + #define SGE_TIMER_VALUE_0_AND_1 0x10b8 #define TIMERVALUE0_MASK 0xU #define TIMERVALUE0_SHIFT 16 -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe lin
[PATCH v2 net-next 09/22] cxgb4: Update driver version and description
From: Santosh Rastapur Signed-off-by: Santosh Rastapur Signed-off-by: Vipul Pandya --- v2: Replaced #ifdef with portable interface wmb in ring_tx_db drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index eceee44..c502e36 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -68,8 +68,8 @@ #include "t4fw_api.h" #include "l2t.h" -#define DRV_VERSION "1.3.0-ko" -#define DRV_DESC "Chelsio T4 Network Driver" +#define DRV_VERSION "2.0.0-ko" +#define DRV_DESC "Chelsio T4/T5 Network Driver" /* * Max interrupt hold-off timer value in us. Queues fall back to this value -- 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 v2 net-next 07/22] cxgb4: Add T5 debugfs support
From: Santosh Rastapur Signed-off-by: Santosh Rastapur Signed-off-by: Vipul Pandya --- v2: Replaced #ifdef with portable interface wmb in ring_tx_db drivers/net/ethernet/chelsio/cxgb4/cxgb4.h |3 +- drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 55 +--- drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 104 -- 3 files changed, 119 insertions(+), 43 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index f8ff30e..45b18bd 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -908,7 +908,8 @@ int t4_config_rss_range(struct adapter *adapter, int mbox, unsigned int viid, int start, int n, const u16 *rspq, unsigned int nrspq); int t4_config_glbl_rss(struct adapter *adapter, int mbox, unsigned int mode, unsigned int flags); -int t4_mc_read(struct adapter *adap, u32 addr, __be32 *data, u64 *parity); +int t4_mc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, + u64 *parity); int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *parity); diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 177d0c1..ca88070 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -2843,8 +2843,8 @@ static ssize_t mem_read(struct file *file, char __user *buf, size_t count, int ret, ofst; __be32 data[16]; - if (mem == MEM_MC) - ret = t4_mc_read(adap, pos, data, NULL); + if ((mem == MEM_MC) || (mem == MEM_MC1)) + ret = t4_mc_read(adap, mem % MEM_MC, pos, data, NULL); else ret = t4_edc_read(adap, mem, pos, data, NULL); if (ret) @@ -2885,18 +2885,37 @@ static void add_debugfs_mem(struct adapter *adap, const char *name, static int setup_debugfs(struct adapter *adap) { int i; + u32 size; if (IS_ERR_OR_NULL(adap->debugfs_root)) return -1; i = t4_read_reg(adap, MA_TARGET_MEM_ENABLE); - if (i & EDRAM0_ENABLE) - add_debugfs_mem(adap, "edc0", MEM_EDC0, 5); - if (i & EDRAM1_ENABLE) - add_debugfs_mem(adap, "edc1", MEM_EDC1, 5); - if (i & EXT_MEM_ENABLE) - add_debugfs_mem(adap, "mc", MEM_MC, - EXT_MEM_SIZE_GET(t4_read_reg(adap, MA_EXT_MEMORY_BAR))); + if (i & EDRAM0_ENABLE) { + size = t4_read_reg(adap, MA_EDRAM0_BAR); + add_debugfs_mem(adap, "edc0", MEM_EDC0, EDRAM_SIZE_GET(size)); + } + if (i & EDRAM1_ENABLE) { + size = t4_read_reg(adap, MA_EDRAM1_BAR); + add_debugfs_mem(adap, "edc1", MEM_EDC1, EDRAM_SIZE_GET(size)); + } + if (is_t4(adap->chip)) { + size = t4_read_reg(adap, MA_EXT_MEMORY_BAR); + if (i & EXT_MEM_ENABLE) + add_debugfs_mem(adap, "mc", MEM_MC, + EXT_MEM_SIZE_GET(size)); + } else { + if (i & EXT_MEM_ENABLE) { + size = t4_read_reg(adap, MA_EXT_MEMORY_BAR); + add_debugfs_mem(adap, "mc0", MEM_MC0, + EXT_MEM_SIZE_GET(size)); + } + if (i & EXT_MEM1_ENABLE) { + size = t4_read_reg(adap, MA_EXT_MEMORY1_BAR); + add_debugfs_mem(adap, "mc1", MEM_MC1, + EXT_MEM_SIZE_GET(size)); + } + } if (adap->l2t) debugfs_create_file("l2t", S_IRUSR, adap->debugfs_root, adap, &t4_l2t_fops); @@ -4101,17 +4120,27 @@ void t4_fatal_err(struct adapter *adap) static void setup_memwin(struct adapter *adap) { - u32 bar0; + u32 bar0, mem_win0_base, mem_win1_base, mem_win2_base; bar0 = pci_resource_start(adap->pdev, 0); /* truncation intentional */ + if (is_t4(adap->chip)) { + mem_win0_base = bar0 + MEMWIN0_BASE; + mem_win1_base = bar0 + MEMWIN1_BASE; + mem_win2_base = bar0 + MEMWIN2_BASE; + } else { + /* For T5, only relative offset inside the PCIe BAR is passed */ + mem_win0_base = MEMWIN0_BASE; + mem_win1_base = MEMWIN1_BASE_T5; + mem_win2_base = MEMWIN2_BASE_T5; + } t4_write_reg(adap, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 0), -(bar0 + MEMWIN0_BASE) | BIR(0) | +mem_win0_base | BIR(0) | WINDOW(ilog2(MEMWIN0_APERTURE) - 10)); t4_write_reg(adap, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 1), -
[PATCH v2 net-next 06/22] cxgb4: Enable doorbell drop recovery only for T4 adapter
From: Santosh Rastapur Signed-off-by: Santosh Rastapur Signed-off-by: Vipul Pandya --- v2: Replaced #ifdef with portable interface wmb in ring_tx_db drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 87 ++ 1 files changed, 71 insertions(+), 16 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index ce1451c..177d0c1 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -3227,10 +3227,18 @@ EXPORT_SYMBOL(cxgb4_port_chan); unsigned int cxgb4_dbfifo_count(const struct net_device *dev, int lpfifo) { struct adapter *adap = netdev2adap(dev); - u32 v; + u32 v1, v2, lp_count, hp_count; - v = t4_read_reg(adap, A_SGE_DBFIFO_STATUS); - return lpfifo ? G_LP_COUNT(v) : G_HP_COUNT(v); + v1 = t4_read_reg(adap, A_SGE_DBFIFO_STATUS); + v2 = t4_read_reg(adap, SGE_DBFIFO_STATUS2); + if (is_t4(adap->chip)) { + lp_count = G_LP_COUNT(v1); + hp_count = G_HP_COUNT(v1); + } else { + lp_count = G_LP_COUNT_T5(v1); + hp_count = G_HP_COUNT_T5(v2); + } + return lpfifo ? lp_count : hp_count; } EXPORT_SYMBOL(cxgb4_dbfifo_count); @@ -3368,14 +3376,23 @@ static struct notifier_block cxgb4_netevent_nb = { static void drain_db_fifo(struct adapter *adap, int usecs) { - u32 v; + u32 v1, v2, lp_count, hp_count; do { + v1 = t4_read_reg(adap, A_SGE_DBFIFO_STATUS); + v2 = t4_read_reg(adap, SGE_DBFIFO_STATUS2); + if (is_t4(adap->chip)) { + lp_count = G_LP_COUNT(v1); + hp_count = G_HP_COUNT(v1); + } else { + lp_count = G_LP_COUNT_T5(v1); + hp_count = G_HP_COUNT_T5(v2); + } + + if (lp_count == 0 && hp_count == 0) + break; set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(usecs_to_jiffies(usecs)); - v = t4_read_reg(adap, A_SGE_DBFIFO_STATUS); - if (G_LP_COUNT(v) == 0 && G_HP_COUNT(v) == 0) - break; } while (1); } @@ -3484,24 +3501,62 @@ static void process_db_drop(struct work_struct *work) adap = container_of(work, struct adapter, db_drop_task); + if (is_t4(adap->chip)) { + disable_dbs(adap); + notify_rdma_uld(adap, CXGB4_CONTROL_DB_DROP); + drain_db_fifo(adap, 1); + recover_all_queues(adap); + enable_dbs(adap); + } else { + u32 dropped_db = t4_read_reg(adap, 0x010ac); + u16 qid = (dropped_db >> 15) & 0x1; + u16 pidx_inc = dropped_db & 0x1fff; + unsigned int s_qpp; + unsigned short udb_density; + unsigned long qpshift; + int page; + u32 udb; + + dev_warn(adap->pdev_dev, +"Dropped DB 0x%x qid %d bar2 %d coalesce %d pidx %d\n", +dropped_db, qid, +(dropped_db >> 14) & 1, +(dropped_db >> 13) & 1, +pidx_inc); + + drain_db_fifo(adap, 1); + + s_qpp = QUEUESPERPAGEPF1 * adap->fn; + udb_density = 1 << QUEUESPERPAGEPF0_GET(t4_read_reg(adap, + SGE_EGRESS_QUEUES_PER_PAGE_PF) >> s_qpp); + qpshift = PAGE_SHIFT - ilog2(udb_density); + udb = qid << qpshift; + udb &= PAGE_MASK; + page = udb / PAGE_SIZE; + udb += (qid - (page * udb_density)) * 128; + + writel(PIDX(pidx_inc), adap->bar2 + udb + 8); + + /* Re-enable BAR2 WC */ + t4_set_reg_field(adap, 0x10b0, 1<<15, 1<<15); + } + t4_set_reg_field(adap, A_SGE_DOORBELL_CONTROL, F_DROPPED_DB, 0); - disable_dbs(adap); - notify_rdma_uld(adap, CXGB4_CONTROL_DB_DROP); - drain_db_fifo(adap, 1); - recover_all_queues(adap); - enable_dbs(adap); } void t4_db_full(struct adapter *adap) { - t4_set_reg_field(adap, SGE_INT_ENABLE3, -DBFIFO_HP_INT | DBFIFO_LP_INT, 0); - queue_work(workq, &adap->db_full_task); + if (is_t4(adap->chip)) { + t4_set_reg_field(adap, SGE_INT_ENABLE3, +DBFIFO_HP_INT | DBFIFO_LP_INT, 0); + queue_work(workq, &adap->db_full_task); + } } void t4_db_dropped(struct adapter *adap) { - queue_work(workq, &adap->db_drop_task); + if (is_t4(adap->chip)) + queue_work(workq, &adap->db_drop_task); } static void uld_attach(struct adapter *adap, unsigned int uld) -- 1.7.1 -- To unsubscribe from this list: send t
[PATCH v2 net-next 02/22] cxgb4: Add macros, structures and inline functions for T5
From: Santosh Rastapur Signed-off-by: Santosh Rastapur Signed-off-by: Vipul Pandya --- v2: Replaced #ifdef with portable interface wmb in ring_tx_db drivers/net/ethernet/chelsio/cxgb4/cxgb4.h| 50 - drivers/net/ethernet/chelsio/cxgb4/t4_msg.h | 45 ++ drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h |2 +- 3 files changed, 95 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index 6db997c..a91dea6 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -54,6 +54,10 @@ #define FW_VERSION_MINOR 1 #define FW_VERSION_MICRO 0 +#define FW_VERSION_MAJOR_T5 0 +#define FW_VERSION_MINOR_T5 0 +#define FW_VERSION_MICRO_T5 0 + #define CH_WARN(adap, fmt, ...) dev_warn(adap->pdev_dev, fmt, ## __VA_ARGS__) enum { @@ -66,7 +70,9 @@ enum { enum { MEM_EDC0, MEM_EDC1, - MEM_MC + MEM_MC, + MEM_MC0 = MEM_MC, + MEM_MC1 }; enum { @@ -74,8 +80,10 @@ enum { MEMWIN0_BASE = 0x1b800, MEMWIN1_APERTURE = 32768, MEMWIN1_BASE = 0x28000, + MEMWIN1_BASE_T5 = 0x52000, MEMWIN2_APERTURE = 65536, MEMWIN2_BASE = 0x3, + MEMWIN2_BASE_T5 = 0x54000, }; enum dev_master { @@ -504,6 +512,35 @@ struct sge { struct l2t_data; +#define CHELSIO_CHIP_CODE(version, revision) (((version) << 4) | (revision)) +#define CHELSIO_CHIP_VERSION(code) ((code) >> 4) +#define CHELSIO_CHIP_RELEASE(code) ((code) & 0xf) + +#define CHELSIO_T4 0x4 +#define CHELSIO_T5 0x5 + +enum chip_type { + T4_A1 = CHELSIO_CHIP_CODE(CHELSIO_T4, 0), + T4_A2 = CHELSIO_CHIP_CODE(CHELSIO_T4, 1), + T4_A3 = CHELSIO_CHIP_CODE(CHELSIO_T4, 2), + T4_FIRST_REV= T4_A1, + T4_LAST_REV = T4_A3, + + T5_A1 = CHELSIO_CHIP_CODE(CHELSIO_T5, 0), + T5_FIRST_REV= T5_A1, + T5_LAST_REV = T5_A1, +}; + +#ifdef CONFIG_PCI_IOV + +/* T4 - 4 PFs support SRIOV + * T5 - 8 PFs support SRIOV + */ +#define NUM_OF_PF_WITH_SRIOV_T4 4 +#define NUM_OF_PF_WITH_SRIOV_T5 8 + +#endif + struct adapter { void __iomem *regs; struct pci_dev *pdev; @@ -511,6 +548,7 @@ struct adapter { unsigned int mbox; unsigned int fn; unsigned int flags; + enum chip_type chip; int msg_enable; @@ -673,6 +711,16 @@ enum { VLAN_REWRITE }; +static inline int is_t5(enum chip_type chip) +{ + return (chip >= T5_FIRST_REV && chip <= T5_LAST_REV); +} + +static inline int is_t4(enum chip_type chip) +{ + return (chip >= T4_FIRST_REV && chip <= T4_LAST_REV); +} + static inline u32 t4_read_reg(struct adapter *adap, u32 reg_addr) { return readl(adap->regs + reg_addr); diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h index 261d177..0c9f14f 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h @@ -74,6 +74,7 @@ enum { CPL_PASS_ESTABLISH= 0x41, CPL_RX_DATA_DDP = 0x42, CPL_PASS_ACCEPT_REQ = 0x44, + CPL_TRACE_PKT_T5 = 0x48, CPL_RDMA_READ_REQ = 0x60, @@ -287,6 +288,23 @@ struct cpl_act_open_req { __be32 opt2; }; +#define S_FILTER_TUPLE 24 +#define M_FILTER_TUPLE 0xFF +#define V_FILTER_TUPLE(x) ((x) << S_FILTER_TUPLE) +#define G_FILTER_TUPLE(x) (((x) >> S_FILTER_TUPLE) & M_FILTER_TUPLE) +struct cpl_t5_act_open_req { + WR_HDR; + union opcode_tid ot; + __be16 local_port; + __be16 peer_port; + __be32 local_ip; + __be32 peer_ip; + __be64 opt0; + __be32 rsvd; + __be32 opt2; + __be64 params; +}; + struct cpl_act_open_req6 { WR_HDR; union opcode_tid ot; @@ -566,6 +584,11 @@ struct cpl_rx_pkt { #define V_RX_ETHHDR_LEN(x) ((x) << S_RX_ETHHDR_LEN) #define G_RX_ETHHDR_LEN(x) (((x) >> S_RX_ETHHDR_LEN) & M_RX_ETHHDR_LEN) +#define S_RX_T5_ETHHDR_LEN0 +#define M_RX_T5_ETHHDR_LEN0x3F +#define V_RX_T5_ETHHDR_LEN(x) ((x) << S_RX_T5_ETHHDR_LEN) +#define G_RX_T5_ETHHDR_LEN(x) (((x) >> S_RX_T5_ETHHDR_LEN) & M_RX_T5_ETHHDR_LEN) + #define S_RX_MACIDX8 #define M_RX_MACIDX0x1FF #define V_RX_MACIDX(x) ((x) << S_RX_MACIDX) @@ -612,6 +635,28 @@ struct cpl_trace_pkt { __be64 tstamp; }; +struct cpl_t5_trace_pkt { + __u8 opcode; + __u8 intf; +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u8 runt:4; + __u8 filter_hit:4; + __u8:6; + __u8 err:1; + __u8 trunc:1; +#else + __u8 filter_hit:4; + __u8 runt:4; + __u8 trunc:1; + __u8 err:1; + __u8:6; +#endif + __be16 rsvd; + __be16 len; + __be64 tstamp; + __be64 rsvd1; +}; + struct cpl_l2t_write_req { WR_HDR; union opcode_tid ot; diff --git a/drivers/net/etherne
[PATCH v2 net-next 16/22] RDMA/cxgb4: Map pbl buffers for dma if using DSGL.
Signed-off-by: Vipul Pandya --- v2: Replaced #ifdef with portable interface wmb in ring_tx_db drivers/infiniband/hw/cxgb4/mem.c | 29 +++-- 1 files changed, 23 insertions(+), 6 deletions(-) diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c index 33db9ee..4cb8eb2 100644 --- a/drivers/infiniband/hw/cxgb4/mem.c +++ b/drivers/infiniband/hw/cxgb4/mem.c @@ -51,7 +51,7 @@ module_param(inline_threshold, int, 0644); MODULE_PARM_DESC(inline_threshold, "inline vs dsgl threshold (default=128)"); static int _c4iw_write_mem_dma_aligned(struct c4iw_rdev *rdev, u32 addr, - u32 len, void *data, int wait) + u32 len, dma_addr_t data, int wait) { struct sk_buff *skb; struct ulp_mem_io *req; @@ -88,7 +88,7 @@ static int _c4iw_write_mem_dma_aligned(struct c4iw_rdev *rdev, u32 addr, sgl->cmd_nsge = cpu_to_be32(ULPTX_CMD(ULP_TX_SC_DSGL) | ULPTX_NSGE(1)); sgl->len0 = cpu_to_be32(len); - sgl->addr0 = cpu_to_be64(virt_to_phys(data)); + sgl->addr0 = cpu_to_be64(data); ret = c4iw_ofld_send(rdev, skb); if (ret) @@ -178,6 +178,13 @@ int _c4iw_write_mem_dma(struct c4iw_rdev *rdev, u32 addr, u32 len, void *data) u32 remain = len; u32 dmalen; int ret = 0; + dma_addr_t daddr; + dma_addr_t save; + + daddr = dma_map_single(&rdev->lldi.pdev->dev, data, len, DMA_TO_DEVICE); + if (dma_mapping_error(&rdev->lldi.pdev->dev, daddr)) + return -1; + save = daddr; while (remain > inline_threshold) { if (remain < T4_ULPTX_MAX_DMA) { @@ -188,16 +195,18 @@ int _c4iw_write_mem_dma(struct c4iw_rdev *rdev, u32 addr, u32 len, void *data) } else dmalen = T4_ULPTX_MAX_DMA; remain -= dmalen; - ret = _c4iw_write_mem_dma_aligned(rdev, addr, dmalen, data, + ret = _c4iw_write_mem_dma_aligned(rdev, addr, dmalen, daddr, !remain); if (ret) goto out; addr += dmalen >> 5; data += dmalen; + daddr += dmalen; } if (remain) ret = _c4iw_write_mem_inline(rdev, addr, remain, data); out: + dma_unmap_single(&rdev->lldi.pdev->dev, save, len, DMA_TO_DEVICE); return ret; } @@ -209,9 +218,17 @@ static int write_adapter_mem(struct c4iw_rdev *rdev, u32 addr, u32 len, void *data) { if (is_t5(rdev->lldi.adapter_type) && use_dsgl) { - if (len > inline_threshold) - return _c4iw_write_mem_dma(rdev, addr, len, data); - else + if (len > inline_threshold) { + if (_c4iw_write_mem_dma(rdev, addr, len, data)) { + printk_ratelimited(KERN_WARNING + "%s: dma map" + " failure (non fatal)\n", + pci_name(rdev->lldi.pdev)); + return _c4iw_write_mem_inline(rdev, addr, len, + data); + } else + return 0; + } else return _c4iw_write_mem_inline(rdev, addr, len, data); } else return _c4iw_write_mem_inline(rdev, addr, len, data); -- 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 v2 net-next 14/22] RDMA/cxgb4: Add module_params to enable DB FC & Coalescing on T5
Both DB Flow-Control and DB Coalescing are disabled by default on T5 Signed-off-by: Vipul Pandya --- v2: Replaced #ifdef with portable interface wmb in ring_tx_db drivers/infiniband/hw/cxgb4/device.c | 25 +++-- drivers/infiniband/hw/cxgb4/iw_cxgb4.h |1 + drivers/infiniband/hw/cxgb4/qp.c | 10 ++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c index 3487c08..ae65601 100644 --- a/drivers/infiniband/hw/cxgb4/device.c +++ b/drivers/infiniband/hw/cxgb4/device.c @@ -45,6 +45,16 @@ MODULE_DESCRIPTION("Chelsio T4/T5 RDMA Driver"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_VERSION(DRV_VERSION); +static int allow_db_fc_on_t5; +module_param(allow_db_fc_on_t5, int, 0644); +MODULE_PARM_DESC(allow_db_fc_on_t5, +"Allow DB Flow Control on T5 (default = 0)"); + +static int allow_db_coalescing_on_t5; +module_param(allow_db_coalescing_on_t5, int, 0644); +MODULE_PARM_DESC(allow_db_coalescing_on_t5, +"Allow DB Coalescing on T5 (default = 0)"); + struct uld_ctx { struct list_head entry; struct cxgb4_lld_info lldi; @@ -630,8 +640,19 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop) if (!ocqp_supported(infop)) pr_info("%s: On-Chip Queues not supported on this device.\n", pci_name(infop->pdev)); - if (!is_t4(infop->adapter_type)) - db_fc_threshold = 10; + + if (!is_t4(infop->adapter_type)) { + if (!allow_db_fc_on_t5) { + db_fc_threshold = 10; + pr_info("DB Flow Control Disabled.\n"); + } + + if (!allow_db_coalescing_on_t5) { + db_coalescing_threshold = -1; + pr_info("DB Coalescing Disabled.\n"); + } + } + devp = (struct c4iw_dev *)ib_alloc_device(sizeof(*devp)); if (!devp) { printk(KERN_ERR MOD "Cannot allocate ib device\n"); diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h index 34c7e62..4dbe96a 100644 --- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h +++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h @@ -939,6 +939,7 @@ extern struct cxgb4_client t4c_client; extern c4iw_handler_func c4iw_handlers[NUM_CPL_CMDS]; extern int c4iw_max_read_depth; extern int db_fc_threshold; +extern int db_coalescing_threshold; #endif diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c index da4869f..28592d4 100644 --- a/drivers/infiniband/hw/cxgb4/qp.c +++ b/drivers/infiniband/hw/cxgb4/qp.c @@ -1455,8 +1455,9 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp) rhp->db_state = NORMAL; idr_for_each(&rhp->qpidr, enable_qp_db, NULL); } - if (rhp->qpcnt <= db_coalescing_threshold) - cxgb4_enable_db_coalescing(rhp->rdev.lldi.ports[0]); + if (db_coalescing_threshold >= 0) + if (rhp->qpcnt <= db_coalescing_threshold) + cxgb4_enable_db_coalescing(rhp->rdev.lldi.ports[0]); spin_unlock_irq(&rhp->lock); atomic_dec(&qhp->refcnt); wait_event(qhp->wait, !atomic_read(&qhp->refcnt)); @@ -1574,8 +1575,9 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs, rhp->db_state = FLOW_CONTROL; idr_for_each(&rhp->qpidr, disable_qp_db, NULL); } - if (rhp->qpcnt > db_coalescing_threshold) - cxgb4_disable_db_coalescing(rhp->rdev.lldi.ports[0]); + if (db_coalescing_threshold >= 0) + if (rhp->qpcnt > db_coalescing_threshold) + cxgb4_disable_db_coalescing(rhp->rdev.lldi.ports[0]); ret = insert_handle_nolock(rhp, &rhp->qpidr, qhp, qhp->wq.sq.qid); spin_unlock_irq(&rhp->lock); if (ret) -- 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 v2 net-next 12/22] RDMA/cxgb4: Add Support for Chelsio T5 adapter
Adds support for Chelsio T5 adapter. Enables T5's Write Combining feature. Signed-off-by: Vipul Pandya --- v2: Replaced #ifdef with portable interface wmb in ring_tx_db drivers/infiniband/hw/cxgb4/cm.c | 64 +++ drivers/infiniband/hw/cxgb4/device.c | 13 -- drivers/infiniband/hw/cxgb4/iw_cxgb4.h |9 drivers/infiniband/hw/cxgb4/provider.c | 15 +-- drivers/infiniband/hw/cxgb4/qp.c |2 +- drivers/infiniband/hw/cxgb4/t4.h |9 6 files changed, 77 insertions(+), 35 deletions(-) diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 565bfb1..272bf78 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -511,12 +511,16 @@ static unsigned int select_ntuple(struct c4iw_dev *dev, struct dst_entry *dst, static int send_connect(struct c4iw_ep *ep) { struct cpl_act_open_req *req; + struct cpl_t5_act_open_req *t5_req; struct sk_buff *skb; u64 opt0; u32 opt2; unsigned int mtu_idx; int wscale; - int wrlen = roundup(sizeof *req, 16); + int size = is_t4(ep->com.dev->rdev.lldi.adapter_type) ? + sizeof(struct cpl_act_open_req) : + sizeof(struct cpl_t5_act_open_req); + int wrlen = roundup(size, 16); PDBG("%s ep %p atid %u\n", __func__, ep, ep->atid); @@ -552,17 +556,36 @@ static int send_connect(struct c4iw_ep *ep) opt2 |= WND_SCALE_EN(1); t4_set_arp_err_handler(skb, NULL, act_open_req_arp_failure); - req = (struct cpl_act_open_req *) skb_put(skb, wrlen); - INIT_TP_WR(req, 0); - OPCODE_TID(req) = cpu_to_be32( - MK_OPCODE_TID(CPL_ACT_OPEN_REQ, ((ep->rss_qid<<14)|ep->atid))); - req->local_port = ep->com.local_addr.sin_port; - req->peer_port = ep->com.remote_addr.sin_port; - req->local_ip = ep->com.local_addr.sin_addr.s_addr; - req->peer_ip = ep->com.remote_addr.sin_addr.s_addr; - req->opt0 = cpu_to_be64(opt0); - req->params = cpu_to_be32(select_ntuple(ep->com.dev, ep->dst, ep->l2t)); - req->opt2 = cpu_to_be32(opt2); + if (is_t4(ep->com.dev->rdev.lldi.adapter_type)) { + req = (struct cpl_act_open_req *) skb_put(skb, wrlen); + INIT_TP_WR(req, 0); + OPCODE_TID(req) = cpu_to_be32( + MK_OPCODE_TID(CPL_ACT_OPEN_REQ, + ((ep->rss_qid << 14) | ep->atid))); + req->local_port = ep->com.local_addr.sin_port; + req->peer_port = ep->com.remote_addr.sin_port; + req->local_ip = ep->com.local_addr.sin_addr.s_addr; + req->peer_ip = ep->com.remote_addr.sin_addr.s_addr; + req->opt0 = cpu_to_be64(opt0); + req->params = cpu_to_be32(select_ntuple(ep->com.dev, + ep->dst, ep->l2t)); + req->opt2 = cpu_to_be32(opt2); + } else { + t5_req = (struct cpl_t5_act_open_req *) skb_put(skb, wrlen); + INIT_TP_WR(t5_req, 0); + OPCODE_TID(t5_req) = cpu_to_be32( + MK_OPCODE_TID(CPL_ACT_OPEN_REQ, + ((ep->rss_qid << 14) | ep->atid))); + t5_req->local_port = ep->com.local_addr.sin_port; + t5_req->peer_port = ep->com.remote_addr.sin_port; + t5_req->local_ip = ep->com.local_addr.sin_addr.s_addr; + t5_req->peer_ip = ep->com.remote_addr.sin_addr.s_addr; + t5_req->opt0 = cpu_to_be64(opt0); + t5_req->params = cpu_to_be64(V_FILTER_TUPLE( + select_ntuple(ep->com.dev, ep->dst, ep->l2t))); + t5_req->opt2 = cpu_to_be32(opt2); + } + set_bit(ACT_OPEN_REQ, &ep->com.history); return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); } @@ -2869,12 +2892,14 @@ static int deferred_fw6_msg(struct c4iw_dev *dev, struct sk_buff *skb) static void build_cpl_pass_accept_req(struct sk_buff *skb, int stid , u8 tos) { u32 l2info; - u16 vlantag, len, hdr_len; + u16 vlantag, len, hdr_len, eth_hdr_len; u8 intf; struct cpl_rx_pkt *cpl = cplhdr(skb); struct cpl_pass_accept_req *req; struct tcp_options_received tmp_opt; + struct c4iw_dev *dev; + dev = *((struct c4iw_dev **) (skb->cb + sizeof(void *))); /* Store values from cpl_rx_pkt in temporary location. */ vlantag = (__force u16) cpl->vlan; len = (__force u16) cpl->len; @@ -2898,14 +2923,16 @@ static void build_cpl_pass_accept_req(struct sk_buff *skb, int stid , u8 tos) V_SYN_MAC_IDX(G_RX_MACIDX( (__force int) htonl(l2info))) | F_SYN_XACT_MATCH); + eth_hdr_len = is_t4(dev->rdev.lldi.adapter_type) ? +
[PATCH v2 net-next 11/22] cxgb4vf: Add support for Chelsio T5 adapter
From: Santosh Rastapur Signed-off-by: Santosh Rastapur Signed-off-by: Vipul Pandya --- v2: Replaced #ifdef with portable interface wmb in ring_tx_db drivers/net/ethernet/chelsio/cxgb4vf/adapter.h |1 + .../net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c| 35 ++-- drivers/net/ethernet/chelsio/cxgb4vf/sge.c |8 +++- drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h | 24 + drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c | 14 ++-- 5 files changed, 73 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h b/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h index 68eaa9c..be5c7ef 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h +++ b/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h @@ -344,6 +344,7 @@ struct adapter { unsigned long registered_device_map; unsigned long open_device_map; unsigned long flags; + enum chip_type chip; struct adapter_params params; /* queue and interrupt resources */ diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c index 56b46ab..7fcac20 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c @@ -54,8 +54,8 @@ /* * Generic information about the driver. */ -#define DRV_VERSION "1.0.0" -#define DRV_DESC "Chelsio T4 Virtual Function (VF) Network Driver" +#define DRV_VERSION "2.0.0-ko" +#define DRV_DESC "Chelsio T4/T5 Virtual Function (VF) Network Driver" /* * Module Parameters. @@ -1050,7 +1050,7 @@ static inline unsigned int mk_adap_vers(const struct adapter *adapter) /* * Chip version 4, revision 0x3f (cxgb4vf). */ - return 4 | (0x3f << 10); + return CHELSIO_CHIP_VERSION(adapter->chip) | (0x3f << 10); } /* @@ -2099,6 +2099,15 @@ static int adap_init0(struct adapter *adapter) return err; } + switch (adapter->pdev->device >> 12) { + case CHELSIO_T4: + adapter->chip = CHELSIO_CHIP_CODE(CHELSIO_T4, 0); + break; + case CHELSIO_T5: + adapter->chip = CHELSIO_CHIP_CODE(CHELSIO_T5, 0); + break; + } + /* * Grab basic operational parameters. These will predominantly have * been set up by the Physical Function Driver or will be hard coded @@ -2888,6 +2897,26 @@ static struct pci_device_id cxgb4vf_pci_tbl[] = { CH_DEVICE(0x480a, 0), /* T404-bt */ CH_DEVICE(0x480d, 0), /* T480-cr */ CH_DEVICE(0x480e, 0), /* T440-lp-cr */ + CH_DEVICE(0x5800, 0), /* T580-dbg */ + CH_DEVICE(0x5801, 0), /* T520-cr */ + CH_DEVICE(0x5802, 0), /* T522-cr */ + CH_DEVICE(0x5803, 0), /* T540-cr */ + CH_DEVICE(0x5804, 0), /* T520-bch */ + CH_DEVICE(0x5805, 0), /* T540-bch */ + CH_DEVICE(0x5806, 0), /* T540-ch */ + CH_DEVICE(0x5807, 0), /* T520-so */ + CH_DEVICE(0x5808, 0), /* T520-cx */ + CH_DEVICE(0x5809, 0), /* T520-bt */ + CH_DEVICE(0x580a, 0), /* T504-bt */ + CH_DEVICE(0x580b, 0), /* T520-sr */ + CH_DEVICE(0x580c, 0), /* T504-bt */ + CH_DEVICE(0x580d, 0), /* T580-cr */ + CH_DEVICE(0x580e, 0), /* T540-lp-cr */ + CH_DEVICE(0x580f, 0), /* Amsterdam */ + CH_DEVICE(0x5810, 0), /* T580-lp-cr */ + CH_DEVICE(0x5811, 0), /* T520-lp-cr */ + CH_DEVICE(0x5812, 0), /* T560-cr */ + CH_DEVICE(0x5813, 0), /* T580-cr */ { 0, } }; diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c index 9488032..61dfb2a 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c @@ -528,17 +528,21 @@ static void unmap_rx_buf(struct adapter *adapter, struct sge_fl *fl) */ static inline void ring_fl_db(struct adapter *adapter, struct sge_fl *fl) { + u32 val; + /* * The SGE keeps track of its Producer and Consumer Indices in terms * of Egress Queue Units so we can only tell it about integral numbers * of multiples of Free List Entries per Egress Queue Units ... */ if (fl->pend_cred >= FL_PER_EQ_UNIT) { + val = PIDX(fl->pend_cred / FL_PER_EQ_UNIT); + if (!is_t4(adapter->chip)) + val |= DBTYPE(1); wmb(); t4_write_reg(adapter, T4VF_SGE_BASE_ADDR + SGE_VF_KDOORBELL, DBPRIO(1) | -QID(fl->cntxt_id) | -PIDX(fl->pend_cred / FL_PER_EQ_UNIT)); +QID(fl->cntxt_id) | val); fl->pend_cred %= FL_PER_EQ_UNIT; } } diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h index
[PATCH v2 net-next 10/22] cxgb4: Disable SR-IOV support for PF4-7 for T5
From: Santosh Rastapur All T5 adapters will only support VFs on PF0-3 despite the ability of the hardware to support them on PF4-7. This keeps our T4 and T5 adapters more similar which simplifies host driver software. Signed-off-by: Vipul Pandya --- v2: Replaced #ifdef with portable interface wmb in ring_tx_db drivers/net/ethernet/chelsio/cxgb4/cxgb4.h |8 drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 21 ++--- 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index 45b18bd..681804b 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -534,11 +534,11 @@ enum chip_type { #ifdef CONFIG_PCI_IOV -/* T4 - 4 PFs support SRIOV - * T5 - 8 PFs support SRIOV +/* T4 supports SRIOV on PF0-3 and T5 on PF0-7. However, the Serial + * Configuration initialization for T5 only has SR-IOV functionality enabled + * on PF0-3 in order to simplify everything. */ -#define NUM_OF_PF_WITH_SRIOV_T4 4 -#define NUM_OF_PF_WITH_SRIOV_T5 8 +#define NUM_OF_PF_WITH_SRIOV 4 #endif diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index c502e36..a59bb23 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -360,14 +360,13 @@ static bool vf_acls; module_param(vf_acls, bool, 0644); MODULE_PARM_DESC(vf_acls, "if set enable virtualization L2 ACL enforcement"); -/* Since T5 has more num of PFs, using NUM_OF_PF_WITH_SRIOV_T5 - * macro as num_vf array size +/* Configure the number of PCI-E Virtual Function which are to be instantiated + * on SR-IOV Capable Physical Functions. */ -static unsigned int num_vf[NUM_OF_PF_WITH_SRIOV_T5]; +static unsigned int num_vf[NUM_OF_PF_WITH_SRIOV]; module_param_array(num_vf, uint, NULL, 0644); -MODULE_PARM_DESC(num_vf, -"number of VFs for each of PFs 0-3 for T4 and PFs 0-7 for T5"); +MODULE_PARM_DESC(num_vf, "number of VFs for each of PFs 0-3"); #endif /* @@ -4633,10 +4632,8 @@ static int adap_init0_no_config(struct adapter *adapter, int reset) */ { int pf, vf; - int max_no_pf = is_t4(adapter->chip) ? NUM_OF_PF_WITH_SRIOV_T4 : - NUM_OF_PF_WITH_SRIOV_T5; - for (pf = 0; pf < max_no_pf; pf++) { + for (pf = 0; pf < ARRAY_SIZE(num_vf); pf++) { if (num_vf[pf] <= 0) continue; @@ -5483,9 +5480,6 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) struct port_info *pi; bool highdma = false; struct adapter *adapter = NULL; -#ifdef CONFIG_PCI_IOV - int max_no_pf; -#endif printk_once(KERN_INFO "%s - version %s\n", DRV_DESC, DRV_VERSION); @@ -5704,10 +5698,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) sriov: #ifdef CONFIG_PCI_IOV - max_no_pf = is_t4(adapter->chip) ? NUM_OF_PF_WITH_SRIOV_T4 : - NUM_OF_PF_WITH_SRIOV_T5; - - if (func < max_no_pf && num_vf[func] > 0) + if (func < ARRAY_SIZE(num_vf) && num_vf[func] > 0) if (pci_enable_sriov(pdev, num_vf[func]) == 0) dev_info(&pdev->dev, "instantiated %u virtual functions\n", -- 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 v2 net-next 08/22] cxgb4: Add T5 PCI ids
From: Santosh Rastapur Signed-off-by: Santosh Rastapur Signed-off-by: Vipul Pandya --- v2: Replaced #ifdef with portable interface wmb in ring_tx_db drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 38 +++ 1 files changed, 38 insertions(+), 0 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index ca88070..eceee44 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -229,6 +229,44 @@ static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = { CH_DEVICE(0x440a, 4), CH_DEVICE(0x440d, 4), CH_DEVICE(0x440e, 4), + CH_DEVICE(0x5001, 5), + CH_DEVICE(0x5002, 5), + CH_DEVICE(0x5003, 5), + CH_DEVICE(0x5004, 5), + CH_DEVICE(0x5005, 5), + CH_DEVICE(0x5006, 5), + CH_DEVICE(0x5007, 5), + CH_DEVICE(0x5008, 5), + CH_DEVICE(0x5009, 5), + CH_DEVICE(0x500A, 5), + CH_DEVICE(0x500B, 5), + CH_DEVICE(0x500C, 5), + CH_DEVICE(0x500D, 5), + CH_DEVICE(0x500E, 5), + CH_DEVICE(0x500F, 5), + CH_DEVICE(0x5010, 5), + CH_DEVICE(0x5011, 5), + CH_DEVICE(0x5012, 5), + CH_DEVICE(0x5013, 5), + CH_DEVICE(0x5401, 5), + CH_DEVICE(0x5402, 5), + CH_DEVICE(0x5403, 5), + CH_DEVICE(0x5404, 5), + CH_DEVICE(0x5405, 5), + CH_DEVICE(0x5406, 5), + CH_DEVICE(0x5407, 5), + CH_DEVICE(0x5408, 5), + CH_DEVICE(0x5409, 5), + CH_DEVICE(0x540A, 5), + CH_DEVICE(0x540B, 5), + CH_DEVICE(0x540C, 5), + CH_DEVICE(0x540D, 5), + CH_DEVICE(0x540E, 5), + CH_DEVICE(0x540F, 5), + CH_DEVICE(0x5410, 5), + CH_DEVICE(0x5411, 5), + CH_DEVICE(0x5412, 5), + CH_DEVICE(0x5413, 5), { 0, } }; -- 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 v2 net-next 04/22] cxgb4: Dump T5 registers
From: Santosh Rastapur Signed-off-by: Santosh Rastapur Signed-off-by: Vipul Pandya --- v2: Replaced #ifdef with portable interface wmb in ring_tx_db drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 452 ++- 1 files changed, 448 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index dd7bcc2..3d6d23a 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -1340,10 +1340,15 @@ static int get_sset_count(struct net_device *dev, int sset) } #define T4_REGMAP_SIZE (160 * 1024) +#define T5_REGMAP_SIZE (332 * 1024) static int get_regs_len(struct net_device *dev) { - return T4_REGMAP_SIZE; + struct adapter *adap = netdev2adap(dev); + if (is_t4(adap->chip)) + return T4_REGMAP_SIZE; + else + return T5_REGMAP_SIZE; } static int get_eeprom_len(struct net_device *dev) @@ -1448,7 +1453,7 @@ static void reg_block_dump(struct adapter *ap, void *buf, unsigned int start, static void get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf) { - static const unsigned int reg_ranges[] = { + static const unsigned int t4_reg_ranges[] = { 0x1008, 0x1108, 0x1180, 0x11b4, 0x11fc, 0x123c, @@ -1668,13 +1673,452 @@ static void get_regs(struct net_device *dev, struct ethtool_regs *regs, 0x27e00, 0x27e04 }; + static const unsigned int t5_reg_ranges[] = { + 0x1008, 0x1148, + 0x1180, 0x11b4, + 0x11fc, 0x123c, + 0x1280, 0x173c, + 0x1800, 0x18fc, + 0x3000, 0x3028, + 0x3060, 0x30d8, + 0x30e0, 0x30fc, + 0x3140, 0x357c, + 0x35a8, 0x35cc, + 0x35ec, 0x35ec, + 0x3600, 0x5624, + 0x56cc, 0x575c, + 0x580c, 0x5814, + 0x5890, 0x58bc, + 0x5940, 0x59dc, + 0x59fc, 0x5a18, + 0x5a60, 0x5a9c, + 0x5b9c, 0x5bfc, + 0x6000, 0x6040, + 0x6058, 0x614c, + 0x7700, 0x7798, + 0x77c0, 0x78fc, + 0x7b00, 0x7c54, + 0x7d00, 0x7efc, + 0x8dc0, 0x8de0, + 0x8df8, 0x8e84, + 0x8ea0, 0x8f84, + 0x8fc0, 0x90f8, + 0x9400, 0x9470, + 0x9600, 0x96f4, + 0x9800, 0x9808, + 0x9820, 0x983c, + 0x9850, 0x9864, + 0x9c00, 0x9c6c, + 0x9c80, 0x9cec, + 0x9d00, 0x9d6c, + 0x9d80, 0x9dec, + 0x9e00, 0x9e6c, + 0x9e80, 0x9eec, + 0x9f00, 0x9f6c, + 0x9f80, 0xa020, + 0xd004, 0xd03c, + 0xdfc0, 0xdfe0, + 0xe000, 0x11088, + 0x1109c, 0x1117c, + 0x11190, 0x11204, + 0x19040, 0x1906c, + 0x19078, 0x19080, + 0x1908c, 0x19124, + 0x19150, 0x191b0, + 0x191d0, 0x191e8, + 0x19238, 0x19290, + 0x193f8, 0x19474, + 0x19490, 0x194cc, + 0x194f0, 0x194f8, + 0x19c00, 0x19c60, + 0x19c94, 0x19e10, + 0x19e50, 0x19f34, + 0x19f40, 0x19f50, + 0x19f90, 0x19fe4, + 0x1a000, 0x1a06c, + 0x1a0b0, 0x1a120, + 0x1a128, 0x1a138, + 0x1a190, 0x1a1c4, + 0x1a1fc, 0x1a1fc, + 0x1e008, 0x1e00c, + 0x1e040, 0x1e04c, + 0x1e284, 0x1e290, + 0x1e2c0, 0x1e2c0, + 0x1e2e0, 0x1e2e0, + 0x1e300, 0x1e384, + 0x1e3c0, 0x1e3c8, + 0x1e408, 0x1e40c, + 0x1e440, 0x1e44c, + 0x1e684, 0x1e690, + 0x1e6c0, 0x1e6c0, + 0x1e6e0, 0x1e6e0, + 0x1e700, 0x1e784, + 0x1e7c0, 0x1e7c8, + 0x1e808, 0x1e80c, + 0x1e840, 0x1e84c, + 0x1ea84, 0x1ea90, + 0x1eac0, 0x1eac0, + 0x1eae0, 0x1eae0, + 0x1eb00, 0x1eb84, + 0x1ebc0, 0x1ebc8, + 0x1ec08, 0x1ec0c, + 0x1ec40, 0x1ec4c, + 0x1ee84, 0x1ee90, + 0x1eec0, 0x1eec0, + 0x1eee0, 0x1eee0, + 0x1ef00, 0x1ef84, + 0x1efc0, 0x1efc8, + 0x1f008, 0x1f00c, + 0x1f040, 0x1f04c, + 0x1f284, 0x1f290, + 0x1f2c0, 0x1f2c0, + 0x1f2e0, 0x1f2e0, + 0x1f300, 0x1f384, + 0x1f3c0, 0x1f3c8, + 0x1f408, 0x1f40c,
[PATCH v2 net-next 03/22] cxgb4: Initialize T5
From: Santosh Rastapur Signed-off-by: Santosh Rastapur Signed-off-by: Vipul Pandya --- v2: Replaced #ifdef with portable interface wmb in ring_tx_db drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 85 ++--- drivers/net/ethernet/chelsio/cxgb4/sge.c| 37 -- drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 152 --- drivers/net/ethernet/chelsio/cxgb4/t4_hw.h |1 - 4 files changed, 227 insertions(+), 48 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index e707e31..dd7bcc2 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -233,7 +233,9 @@ static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = { }; #define FW_FNAME "cxgb4/t4fw.bin" +#define FW5_FNAME "cxgb4/t5fw.bin" #define FW_CFNAME "cxgb4/t4-config.txt" +#define FW5_CFNAME "cxgb4/t5-config.txt" MODULE_DESCRIPTION(DRV_DESC); MODULE_AUTHOR("Chelsio Communications"); @@ -241,6 +243,7 @@ MODULE_LICENSE("Dual BSD/GPL"); MODULE_VERSION(DRV_VERSION); MODULE_DEVICE_TABLE(pci, cxgb4_pci_tbl); MODULE_FIRMWARE(FW_FNAME); +MODULE_FIRMWARE(FW5_FNAME); /* * Normally we're willing to become the firmware's Master PF but will be happy @@ -319,10 +322,14 @@ static bool vf_acls; module_param(vf_acls, bool, 0644); MODULE_PARM_DESC(vf_acls, "if set enable virtualization L2 ACL enforcement"); -static unsigned int num_vf[4]; +/* Since T5 has more num of PFs, using NUM_OF_PF_WITH_SRIOV_T5 + * macro as num_vf array size + */ +static unsigned int num_vf[NUM_OF_PF_WITH_SRIOV_T5]; module_param_array(num_vf, uint, NULL, 0644); -MODULE_PARM_DESC(num_vf, "number of VFs for each of PFs 0-3"); +MODULE_PARM_DESC(num_vf, +"number of VFs for each of PFs 0-3 for T4 and PFs 0-7 for T5"); #endif /* @@ -1002,21 +1009,36 @@ freeout:t4_free_sge_resources(adap); static int upgrade_fw(struct adapter *adap) { int ret; - u32 vers; + u32 vers, exp_major; const struct fw_hdr *hdr; const struct firmware *fw; struct device *dev = adap->pdev_dev; + char *fw_file_name; - ret = request_firmware(&fw, FW_FNAME, dev); + switch (CHELSIO_CHIP_VERSION(adap->chip)) { + case CHELSIO_T4: + fw_file_name = FW_FNAME; + exp_major = FW_VERSION_MAJOR; + break; + case CHELSIO_T5: + fw_file_name = FW5_FNAME; + exp_major = FW_VERSION_MAJOR_T5; + break; + default: + dev_err(dev, "Unsupported chip type, %x\n", adap->chip); + return -EINVAL; + } + + ret = request_firmware(&fw, fw_file_name, dev); if (ret < 0) { - dev_err(dev, "unable to load firmware image " FW_FNAME - ", error %d\n", ret); + dev_err(dev, "unable to load firmware image %s, error %d\n", + fw_file_name, ret); return ret; } hdr = (const struct fw_hdr *)fw->data; vers = ntohl(hdr->fw_ver); - if (FW_HDR_FW_VER_MAJOR_GET(vers) != FW_VERSION_MAJOR) { + if (FW_HDR_FW_VER_MAJOR_GET(vers) != exp_major) { ret = -EINVAL; /* wrong major version, won't do */ goto out; } @@ -1024,18 +1046,15 @@ static int upgrade_fw(struct adapter *adap) /* * If the flash FW is unusable or we found something newer, load it. */ - if (FW_HDR_FW_VER_MAJOR_GET(adap->params.fw_vers) != FW_VERSION_MAJOR || + if (FW_HDR_FW_VER_MAJOR_GET(adap->params.fw_vers) != exp_major || vers > adap->params.fw_vers) { dev_info(dev, "upgrading firmware ...\n"); ret = t4_fw_upgrade(adap, adap->mbox, fw->data, fw->size, /*force=*/false); if (!ret) - dev_info(dev, "firmware successfully upgraded to " -FW_FNAME " (%d.%d.%d.%d)\n", -FW_HDR_FW_VER_MAJOR_GET(vers), -FW_HDR_FW_VER_MINOR_GET(vers), -FW_HDR_FW_VER_MICRO_GET(vers), -FW_HDR_FW_VER_BUILD_GET(vers)); + dev_info(dev, +"firmware upgraded to version %pI4 from %s\n", +&hdr->fw_ver, fw_file_name); else dev_err(dev, "firmware upgrade failed! err=%d\n", -ret); } else { @@ -1413,7 +1432,8 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats, */ static inline unsigned int mk_adap_vers(const struct adapter *ap) { - return 4 | (ap->params.rev << 10) | (1 << 16); + return CHELSIO_CHIP_VERSION(ap->chip) | + (CHELSIO_CHIP_RELEASE(ap->chip) << 10)
[PATCH v2 net-next 00/22] Add support for Chelsio T5 adapter
Hi All, This patch series adds support for Chelsio's T5 adapter. It also adds support for new features of T5. It adds these in cxgb4, cxgb4vf, RDMA/cxgb4 and csiostor drivers. Chelsio's T5 asic moves the architecture into 40GbE speeds. T5 is a 10/40GbE controller with full offload support of a complete Unified Wire solution comprising NIC, Virtualization, TOE, iWARP RDMA and FCoE. T5 supports all the offload, virtualization and switching capabilities of the existing T4 and adds some new features. The patch series does basic intialization for T5 in each driver. The patch series implements a low latency Write Combining work request path in cxgb4 and RDMA/cxgb4 driver for T5. It supports new T5 feature DSGL in RDMA/cxgb4 driver which enables direct DMA by HW to memory region PBL arrays and fast register PBL arrays from host memory. It adds support for dumping T5 registers, T5's debugfs support and enables doorbell drop recovery only for T4 in cxgb4 driver. To facilitate addition of support in csiostor for future adapters, a new framework for adapter specific operations has been defined. Consequently, T4 and T5 specific operations are now separated into different files. One of the csiostor patches also includes common bug fixes. We are submitting changes in all the drivers for T5 in one series since there are common changes in cxgb4 driver which are required by all the ULDs and csiostor. This way we can avoid build failures, build dependencies and ensure smooth integration. We request to merge this patch series via David Miller's net-next tree. We are copying respective maintainers of all the drivers for reviewing the changes. Kindly let us know in case of any review comments. We have successfully carried out networking, virtualization, iWARP and storage related stress tests on this patch series. Thanks, Vipul Pandya v2: Replaced #ifdef with portable interface wmb in ring_tx_db Arvind Bhushan (4): csiostor: Segregate T4 adapter operations. csiostor: Add T5 adapter operations. csiostor: Header file modifications for chip support and bug fixes. csiostor: Cleanup chip specific operations. Santosh Rastapur (11): cxgb4: Add register definations for T5 cxgb4: Add macros, structures and inline functions for T5 cxgb4: Initialize T5 cxgb4: Dump T5 registers cxgb4: Add T5 write combining support cxgb4: Enable doorbell drop recovery only for T4 adapter cxgb4: Add T5 debugfs support cxgb4: Add T5 PCI ids cxgb4: Update driver version and description cxgb4: Disable SR-IOV support for PF4-7 for T5 cxgb4vf: Add support for Chelsio T5 adapter Vipul Pandya (7): RDMA/cxgb4: Add Support for Chelsio T5 adapter RDMA/cxgb4: Turn off db coalescing when RDMA QPs are in use. RDMA/cxgb4: Add module_params to enable DB FC & Coalescing on T5 RDMA/cxgb4: Use DSGLs for fastreg and adapter memory writes for T5. RDMA/cxgb4: Map pbl buffers for dma if using DSGL. RDMA/cxgb4: Bump tcam_full stat and WR reply timeout RDMA/cxgb4: Fix onchip queue support for T5 drivers/infiniband/hw/cxgb4/cm.c | 66 ++- drivers/infiniband/hw/cxgb4/device.c | 34 +- drivers/infiniband/hw/cxgb4/iw_cxgb4.h | 14 +- drivers/infiniband/hw/cxgb4/mem.c | 155 - drivers/infiniband/hw/cxgb4/provider.c | 15 +- drivers/infiniband/hw/cxgb4/qp.c | 113 ++- drivers/infiniband/hw/cxgb4/t4.h | 11 +- drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 55 ++- drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c| 778 ++-- drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h |3 + drivers/net/ethernet/chelsio/cxgb4/sge.c | 89 ++- drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 256 ++-- drivers/net/ethernet/chelsio/cxgb4/t4_hw.h |1 - drivers/net/ethernet/chelsio/cxgb4/t4_msg.h| 53 ++ drivers/net/ethernet/chelsio/cxgb4/t4_regs.h | 98 +++ drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h |2 +- drivers/net/ethernet/chelsio/cxgb4vf/adapter.h |1 + .../net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c| 35 +- drivers/net/ethernet/chelsio/cxgb4vf/sge.c |8 +- drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h | 24 + drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c | 14 +- drivers/scsi/csiostor/Makefile |3 +- drivers/scsi/csiostor/csio_hw.c| 559 +++--- drivers/scsi/csiostor/csio_hw.h| 47 +- drivers/scsi/csiostor/csio_hw_chip.h | 175 + drivers/scsi/csiostor/csio_hw_t4.c | 403 ++ drivers/scsi/csiostor/csio_hw_t5.c | 397 ++ drivers/scsi/csiostor/csio_init.c | 48 +- drivers/scsi/csiostor/csio_init.h | 29 +- drivers/scsi/csiostor/csio_lnode.h |2 +- drivers/scsi/csiostor/csio_rnode.c
Re: [patch] [SCSI] mpt3sas: move dereference under check
On Thu, Mar 14, 2013 at 06:52:35PM +0530, Reddy, Sreekanth wrote: > Hi Dan Carpenter, > > While analyzing this patch, I have added some debugging prints to > print the address referenced by the IOC->sense_dma_pool before and > after pci_pool_free() API and I have observed that the address > referenced by this pointer is same before and after calling > pci_pool_free() API. Please let me know if you have any case > where you have seen ioc->sense_dma_pool is dereferenced after > calling pci_pool_free API. > > And we are checking this ioc->sense_dma_pool pointer to NULL value > for safe side even it is not assigned to NULL value anywhere in > the driver code. Thanks for looking at this. I hope you don't mind, but I've added linux-scsi back to the CC. This is a static checker which is complaining that the code is not checking for NULL consistently. If "ioc->sense_dma_pool" is NULL then we will crash inside pci_pool_free(). The NULL dereference is on the line where we do: mm/dmapool.c 391 void dma_pool_free(struct dma_pool *pool, void *vaddr, dma_addr_t dma) 392 { 393 struct dma_page *page; 394 unsigned long flags; 395 unsigned int offset; 396 397 spin_lock_irqsave(&pool->lock, flags); ^^^ This dereference will cause a crash because we call pci_pool_free() without testing for NULL. 398 page = pool_find_page(pool, dma); In other words: drivers/scsi/mpt3sas/mpt3sas_base.c 2481 if (ioc->sense) { 2482 pci_pool_free(ioc->sense_dma_pool, ioc->sense, ioc->sense_dma); ^ We crash on this line before we reach the NULL test on the next line. 2483 if (ioc->sense_dma_pool) 2484 pci_pool_destroy(ioc->sense_dma_pool); I've looked at the code, and you're right that if (ioc->sense) { is non-NULL that means ->sense_dma_pool is non-NULL. ioc->sense is allocated from the DMA pool. I would like to just remove the test and silence the warning message. regards, dan carpenter -- 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: [RFC 10/11] iser-target: Add logic for core
On 08/03/2013 03:45, Nicholas A. Bellinger wrote: +void +iser_cq_tx_tasklet(unsigned long data) +{ + struct isert_conn *isert_conn = (struct isert_conn *)data; + struct ib_cq *tx_cq = isert_conn->conn_tx_cq; + struct iser_tx_desc *tx_desc; + struct ib_wc wc; + + while (ib_poll_cq(tx_cq, 1, &wc) == 1) { + tx_desc = (struct iser_tx_desc *)(unsigned long)wc.wr_id; + + if (wc.status == IB_WC_SUCCESS) { + isert_send_completion(tx_desc, isert_conn); + } else { + pr_debug("TX wc.status != IB_WC_SUCCESS >>\n"); + isert_dump_ib_wc(&wc); + atomic_dec(&isert_conn->post_send_buf_count); + isert_cq_comp_err(tx_desc, isert_conn); + } + } + + ib_req_notify_cq(tx_cq, IB_CQ_NEXT_COMP); +} + +void +isert_cq_tx_callback(struct ib_cq *cq, void *context) +{ + struct isert_conn *isert_conn = context; + + tasklet_schedule(&isert_conn->conn_tx_tasklet); +} + +void +iser_cq_rx_tasklet(unsigned long data) +{ + struct isert_conn *isert_conn = (struct isert_conn *)data; + struct ib_cq *rx_cq = isert_conn->conn_rx_cq; + struct iser_rx_desc *rx_desc; + struct ib_wc wc; + unsigned long xfer_len; + + while (ib_poll_cq(rx_cq, 1, &wc) == 1) { + rx_desc = (struct iser_rx_desc *)(unsigned long)wc.wr_id; + + if (wc.status == IB_WC_SUCCESS) { + xfer_len = (unsigned long)wc.byte_len; + isert_rx_completion(rx_desc, isert_conn, xfer_len); + } else { + pr_debug("RX wc.status != IB_WC_SUCCESS >>\n"); + if (wc.status != IB_WC_WR_FLUSH_ERR) + isert_dump_ib_wc(&wc); + + isert_conn->post_recv_buf_count--; + isert_cq_comp_err(NULL, isert_conn); + } + } + + ib_req_notify_cq(rx_cq, IB_CQ_NEXT_COMP); +} We currently have here the following sequence of calls isert_cq_rx_callback --> tasklet_schedule ... --> ... ib_poll_cq --> isert_rx_completion --> isert_rx_queue_desc --> isert_rx_queue_desc --> queue_work (context switch) isert_cq_tx_callback --> tasklet_schedule ... --> ... ib_poll_cq --> isert_send_completion --> isert_completion_rdma_read --> queue_work (context switch) which means we have one context switch from the CQ callback to tasklet and then a PER IO context switch from the tasklet to a kernel thread context which you might need for IO submission into the backing store. This can be optimized by having one context switch from the isert cq callbacks to a kernel thread, with the work item being "do polling" and then from the cq polling code do the submission into the backing store without any further context switches. Or. + +void +isert_cq_rx_callback(struct ib_cq *cq, void *context) +{ + struct isert_conn *isert_conn = context; + + tasklet_schedule(&isert_conn->conn_rx_tasklet); +} -- 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: [RFC 09/11] iser-target: Add logic for verbs
On 08/03/2013 03:45, Nicholas A. Bellinger wrote: isert_conn->conn_rx_cq = ib_create_cq(ib_dev, isert_cq_rx_callback, + isert_cq_event_callback, + (void *)isert_conn, + ISER_MAX_RX_CQ_LEN, 0); [...] + + isert_conn->conn_tx_cq = ib_create_cq(ib_dev, isert_cq_tx_callback, + isert_cq_event_callback, + (void *)isert_conn, + ISER_MAX_TX_CQ_LEN, 0); Two comments here: 1. This code always attaches the CQ to vector #0 of the IB device. Typically vectors are associated with IRQs and IRQs are "affiniated" with cores, so processing of completions for all connections will be carried out on single core at a given time. What can be done here is to use different vectors for different CQs. The possible vector values are from 0 to ib_dev->num_comp_vectors - 1 2. A dedicated CQ pair is used per connection which might not scale well. What can be done here, is to use a global context per IB device which holds a pool of CQs (created on different vectors, per the previous item), and for each new connection, attach its QP to a CQ pair from this pool, e.g as done in drivers/infiniband/ulp/iser/iser_verbs.c :: iser_create_device_ib_res() note that FWIW this context can hold also a global PD and DMA_MR objects to be used by all the connections opened on the device. The context can be opened on demand (1st connection that hits this IB device) and closed on non-demand (last connection). Or. -- 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 V2 05/12] pm80xx: MSI-X implementation for using 64 interrupts
Sorry for the late reply. On 03/14/2013 12:04 PM, Anand wrote: From 62b6f575d1978a965339c69158bd10d0529815fb Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Mon, 11 Mar 2013 20:20:19 +0530 Subject: [PATCH V2 05/12] pm80xx: MSI-X implementation for using 64 interrupts Implementation of interrupt handlers and tasklets to support upto 64 interrupt for the device. Signed-off-by: Sakthivel K Signed-off-by: Anand Kumar S Ack-by: Jack Wang --- drivers/scsi/pm8001/pm8001_init.c | 456 +++-- drivers/scsi/pm8001/pm8001_sas.h |1 + 2 files changed, 432 insertions(+), 25 deletions(-) diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index e8a983f..95b6966 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -163,24 +163,33 @@ static void pm8001_free(struct pm8001_hba_info *pm8001_ha) } #ifdef PM8001_USE_TASKLET + +/** + * tasklet for 64 msi-x interrupt handler + * @opaque: the passed general host adapter struct + * Note: pm8001_tasklet is common for pm8001 & pm80xx + */ static void pm8001_tasklet(unsigned long opaque) { struct pm8001_hba_info *pm8001_ha; + u32 vec; pm8001_ha = (struct pm8001_hba_info *)opaque; if (unlikely(!pm8001_ha)) BUG_ON(1); - PM8001_CHIP_DISP->isr(pm8001_ha, 0); + vec = pm8001_ha->int_vector; + PM8001_CHIP_DISP->isr(pm8001_ha, vec); } #endif +/** + * pm8001_interrupt_handler_x -main interrupt handler invokde for all interrupt. + * It obtains the vector number and calls the equivalent bottom half or services + * directly. + * @vec: vector number; will be 0 for none msi-x operation + * @opaque: the passed general host adapter struct + */ - /** - * pm8001_interrupt - when HBA originate a interrupt,we should invoke this - * dispatcher to handle each case. - * @irq: irq number. - * @opaque: the passed general host adapter struct - */ -static irqreturn_t pm8001_interrupt(int irq, void *opaque) +static inline irqreturn_t pm8001_interrupt_handler_x(int vec, void *opaque) { struct pm8001_hba_info *pm8001_ha; irqreturn_t ret = IRQ_HANDLED; @@ -190,6 +199,7 @@ static irqreturn_t pm8001_interrupt(int irq, void *opaque) return IRQ_NONE; if (!PM8001_CHIP_DISP->is_our_interupt(pm8001_ha)) return IRQ_NONE; + pm8001_ha->int_vector = vec; #ifdef PM8001_USE_TASKLET tasklet_schedule(&pm8001_ha->tasklet); #else @@ -198,6 +208,365 @@ static irqreturn_t pm8001_interrupt(int irq, void *opaque) return ret; } +/* 64 interrupt handlers for 64 msi-x vectors */ +static irqreturn_t pm8001_interrupt_handler0(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(0, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler1(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(1, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler2(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(2, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler3(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(3, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler4(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(4, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler5(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(5, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler6(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(6, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler7(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(7, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler8(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(8, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler9(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(9, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler10(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(10, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler11(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(11, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler12(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(12, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler13(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(13, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler14(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(14, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler15(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(15, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler16(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(16, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler17(int irq, void *dev_id) +{ +
Re: [RFC 09/11] iser-target: Add logic for verbs
On 08/03/2013 03:45, Nicholas A. Bellinger wrote: +++ b/drivers/infiniband/ulp/isert/isert_verbs.c +#define ISERT_ADDR_ROUTE_TIMEOUT 1000 remove this define, its irrelevant and you don't use that anywhere +static void +isert_qp_event_callback(struct ib_event *e, void *context) +{ + pr_err("isert_qp_event_callback event: %d\n", e->event); +} To be on the safe side, when the event is IB_EVENT_COMM_EST (which means that the login request was received by the HCA before the connection was fully established), call rdma_notify (id, IB_EVENT_COMM_EST) with the id being the one pointed from qp->qp_context->isert_conn + +static int +isert_query_device(struct ib_device *ib_dev, struct ib_device_attr *devattr) +{ + int ret; + + ret = ib_query_device(ib_dev, devattr); + if (ret) { + pr_err("ib_query_device() failed: %d\n", ret); + return ret; + } + pr_debug("devattr->max_mr_size: 0x%016Lx\n", devattr->max_mr_size); running user space "ibv_devinfo -v" will give the same effect... no need to dump this here, maybe except for max_sge that you need. + pr_debug("devattr->page_size_cap: 0x%016Lx\n", devattr->page_size_cap); + pr_debug("devattr->max_qp: %d\n", devattr->max_qp); + pr_debug("devattr->max_qp_wr: %d\n", devattr->max_qp_wr); + pr_debug("devattr->device_cap_flags: 0x%08x\n", devattr->device_cap_flags); + pr_debug("devattr->max_sge: %d\n", devattr->max_sge); + pr_debug("devattr->max_sge_rd: %d\n", devattr->max_sge_rd); + pr_debug("devattr->max_cq: %d\n", devattr->max_cq); + pr_debug("devattr->max_cqe: %d\n", devattr->max_cqe); + pr_debug("devattr->max_mr: %d\n", devattr->max_mr); + pr_debug("devattr->max_pd: %d\n", devattr->max_pd); + pr_debug("devattr->max_rdd: %d\n", devattr->max_rdd); + pr_debug("devattr->max_mw: %d\n", devattr->max_mw); + pr_debug("devattr->max_srq: %d\n", devattr->max_srq); + pr_debug("devattr->max_srq_wr: %d\n", devattr->max_srq_wr); + pr_debug("devattr->max_srq_sge: %d\n", devattr->max_srq_sge); + + return 0; +} [...] + + +int +isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) +{ + int ret = 0; + + pr_debug("isert_cma_handler: event %d status %d conn %p id %p\n", + event->event, event->status, cma_id->context, cma_id); + + switch (event->event) { + case RDMA_CM_EVENT_CONNECT_REQUEST: + pr_debug("RDMA_CM_EVENT_CONNECT_REQUEST: >>>\n"); + ret = isert_connect_request(cma_id, event); + break; + case RDMA_CM_EVENT_ESTABLISHED: + pr_debug("RDMA_CM_EVENT_ESTABLISHED >>\n"); + isert_connected_handler(cma_id); + break; + case RDMA_CM_EVENT_DISCONNECTED: + pr_debug("RDMA_CM_EVENT_DISCONNECTED: >>\n"); + isert_disconnected_handler(cma_id); + break; + case RDMA_CM_EVENT_DEVICE_REMOVAL: + case RDMA_CM_EVENT_ADDR_CHANGE: + break; + case RDMA_CM_EVENT_ADDR_ERROR: + case RDMA_CM_EVENT_ROUTE_ERROR: + case RDMA_CM_EVENT_CONNECT_ERROR: + default: + pr_err("Unknown RDMA CMA event: %d\n", event->event); + break; + } + ADDR_ERROR and ROUTE_ERROR you can remove from here, since you don't call rdma_resolve_addr nor rdma_resolve_route, they will not be delivered to you. -- 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: [RESEND] [PATCH 05/13] pm80xx: MSI-X implementation for using 64 interrupts
Hi Hannes, I have addressed your comment and merged individual tasklet to one and have resubmitted the patchset. Regards Anand -Original Message- From: Hannes Reinecke [mailto:h...@suse.de] Sent: Monday, March 04, 2013 3:46 PM To: Anand Kumar Santhanam Cc: linux-scsi@vger.kernel.org; Harry Yang; jack_w...@usish.com; Vishwanath Maram; Sangeetha Gnanasekaran Subject: Re: [RESEND] [PATCH 05/13] pm80xx: MSI-X implementation for using 64 interrupts On 03/02/2013 05:48 PM, Anand wrote: > From c5db2e0b6cf65fbef66fb2f4e345bf6856e242a4 Mon Sep 17 00:00:00 > 2001 > From: Sakthivel K > Date: Wed, 27 Feb 2013 20:32:56 +0530 > Subject: [PATCH 05/13] 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 > Ack-by: Jack Wang > --- > drivers/scsi/pm8001/pm8001_init.c | 1233 > - > drivers/scsi/pm8001/pm8001_sas.h |3 +- > 2 files changed, 1205 insertions(+), 31 deletions(-) > > diff --git a/drivers/scsi/pm8001/pm8001_init.c > b/drivers/scsi/pm8001/pm8001_init.c > index e8a983f..f0c5075 100644 > --- 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); } [ ... ] This is stupid. Please merge all the individual tasklets etc. Having 64 identical functions makes the code unreadable and unmaintainable. Cheers, Hannes -- Dr. Hannes Reinecke zSeries & Storage h...@suse.de +49 911 74053 688 SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg GF: J. Hawn, J. Guild, F. Imendörffer, HRB 16746 (AG Nürnberg) -- 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: [RFC 10/11] iser-target: Add logic for core
On 08/03/2013 03:45, Nicholas A. Bellinger wrote: +void +isert_dump_ib_wc(struct ib_wc *wc) +{ + pr_debug("wc->wr_id: %llu\n", wc->wr_id); + pr_debug("wc->status: 0x%08x\n", wc->status); This helper is called for a CQ completion with error, but when this happens all the WC fields except for the wr_id and the status aren't defined, so there's no point in dumping them (can be terribly misleading) + pr_debug("wc->opcode: 0x%08x\n", wc->opcode); + pr_debug("wc->vendor_err: 0x%08x\n", wc->vendor_err); + pr_debug("wc->byte_len: %u\n", wc->byte_len); + pr_debug("wc->qp: %p\n", wc->qp); + pr_debug("wc->src_qp: %u\n", wc->src_qp); + pr_debug("wc->wc_flags: 0x%08x\n", wc->wc_flags); + pr_debug("wc->pkey_index: %hu\n", wc->pkey_index); + pr_debug("wc->slid: %hu\n", wc->slid); + pr_debug("wc->sl: 0x%02x\n", wc->sl); + pr_debug("wc->dlid_path_bits: 0x%02x\n", wc->dlid_path_bits); + pr_debug("wc->port_num: 0x%02x\n", wc->port_num); +} + +void +iser_cq_tx_tasklet(unsigned long data) +{ + struct isert_conn *isert_conn = (struct isert_conn *)data; + struct ib_cq *tx_cq = isert_conn->conn_tx_cq; + struct iser_tx_desc *tx_desc; + struct ib_wc wc; + + while (ib_poll_cq(tx_cq, 1, &wc) == 1) { + tx_desc = (struct iser_tx_desc *)(unsigned long)wc.wr_id; + + if (wc.status == IB_WC_SUCCESS) { + isert_send_completion(tx_desc, isert_conn); + } else { + pr_debug("TX wc.status != IB_WC_SUCCESS >>\n"); + isert_dump_ib_wc(&wc); + atomic_dec(&isert_conn->post_send_buf_count); + isert_cq_comp_err(tx_desc, isert_conn); + } + } + + ib_req_notify_cq(tx_cq, IB_CQ_NEXT_COMP); +} + +void +isert_cq_tx_callback(struct ib_cq *cq, void *context) +{ + struct isert_conn *isert_conn = context; + + tasklet_schedule(&isert_conn->conn_tx_tasklet); +} + +void +iser_cq_rx_tasklet(unsigned long data) +{ + struct isert_conn *isert_conn = (struct isert_conn *)data; + struct ib_cq *rx_cq = isert_conn->conn_rx_cq; + struct iser_rx_desc *rx_desc; + struct ib_wc wc; + unsigned long xfer_len; + + while (ib_poll_cq(rx_cq, 1, &wc) == 1) { + rx_desc = (struct iser_rx_desc *)(unsigned long)wc.wr_id; + + if (wc.status == IB_WC_SUCCESS) { + xfer_len = (unsigned long)wc.byte_len; + isert_rx_completion(rx_desc, isert_conn, xfer_len); + } else { + pr_debug("RX wc.status != IB_WC_SUCCESS >>\n"); + if (wc.status != IB_WC_WR_FLUSH_ERR) + isert_dump_ib_wc(&wc); + + isert_conn->post_recv_buf_count--; + isert_cq_comp_err(NULL, isert_conn); + } + } + + ib_req_notify_cq(rx_cq, IB_CQ_NEXT_COMP); +} -- 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 V2 12/12] pm80xx: thermal, sas controller config and error handling update
>From 375653061c0db3189e9e5678b11291b7b0195ac3 Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Mon, 11 Mar 2013 20:44:36 +0530 Subject: [PATCH V2 12/12] 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 Ack-by: Jack Wang --- 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 100644 --- 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 adda111..27d519d 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -1165,6 +1165,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 100644 --- 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 2fa73fc..29a6a7b 100644 --- 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 pm
[PATCH V2 11/12] pm80xx: NCQ error handling changes
>From 6c5a97ffa25ca47e2403b11e8325c51ac044e501 Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Mon, 11 Mar 2013 20:43:20 +0530 Subject: [PATCH V2 11/12] 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 Ack-by: Jack Wang --- 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 100644 --- 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)
[PATCH V2 09/12] pm80xx: Changed module name and debug messages update
>From 763c1337ae0ec3acea557fa9a4117dd9e2f2ef32 Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Mon, 11 Mar 2013 20:41:38 +0530 Subject: [PATCH V2 09/12] 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 Ack-by: Jack Wang --- drivers/scsi/pm8001/pm8001_hwi.c | 11 ++- drivers/scsi/pm8001/pm8001_init.c | 14 ++ drivers/scsi/pm8001/pm8001_sas.h |6 +++--- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index c124fc6..265dbf4 100644 --- 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 46df0d2..9480a12 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -1068,7 +1068,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; @@ -1116,15 +1116,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) { @@ -1364,7 +1370,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 833fab3..008c2ea 100644 --- 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:" format,\ - __func__, __LINE__, ## arg) +#define pm8001_printk(format, arg...) printk(KERN_INFO "pm80xx %s %d:" \ + format, __func__, __LINE__, ## arg) #define PM8001_CHECK_LOGGING(HBA, LEVEL, CMD) \ do { \ if (unlikely(HBA->logging_level & LEVEL)) \ -- 1.7.1 >From 763c1337ae0ec3acea557fa9a4117dd9e2f2ef32 Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Mon, 11 Mar 2013 20:41:38 +0530 Subject: [PATCH V2 09/12] pm80xx: Changed module name and
[PATCH V2 10/12] pm80xx: WWN Modification for PM8081/88/89 controllers
>From 39041621d54839dcd6878005a48f5ee3e1ec90b9 Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Mon, 11 Mar 2013 20:42:13 +0530 Subject: [PATCH V2 10/12] 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 Ack-by: Jack Wang --- 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 9480a12..adda111 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -936,21 +936,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 >From 39041621d54839dcd6878005a48f5ee3e1ec90b9 Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Mon, 11 Mar 2013 20:42:13 +0530 Subject: [PATCH V2 10/12] 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 Ack-by: Jack Wang --- 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 9480a12..adda111 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -936,21 +936,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.lengt
[PATCH V2 08/12] pm80xx: Firmware flash memory free fix, with addition of new memory region for it
>From 5bb77b58d81591963c8bd6754276c1a78d80c4a4 Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Mon, 11 Mar 2013 20:38:50 +0530 Subject: [PATCH V2 08/12] 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 Ack-by: Jack Wang --- 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 100644 --- 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 100644 --- 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 100644 --- 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; - voi
[PATCH V2 07/12] pm80xx: SPC new firmware changes for device id 0x8081 alone
>From 2083ae66cd04ca9d1ace29bc8f6a159215ece5b6 Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Mon, 11 Mar 2013 20:37:51 +0530 Subject: [PATCH V2 07/12] 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 Ack-by: Jack Wang --- 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 100644 --- 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 100644 --- 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 >From 2083ae66cd04ca9d1ace29bc8f6a159215ece5b6 Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Mon, 11 Mar 2013 20:37:51 +0530 Subject: [PATCH V2 07/12] 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 Ack-by: Jack Wang --- 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 100644 --- 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
[PATCH V2 05/12] pm80xx: MSI-X implementation for using 64 interrupts
>From 62b6f575d1978a965339c69158bd10d0529815fb Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Mon, 11 Mar 2013 20:20:19 +0530 Subject: [PATCH V2 05/12] pm80xx: MSI-X implementation for using 64 interrupts Implementation of interrupt handlers and tasklets to support upto 64 interrupt for the device. Signed-off-by: Sakthivel K Signed-off-by: Anand Kumar S Ack-by: Jack Wang --- drivers/scsi/pm8001/pm8001_init.c | 456 +++-- drivers/scsi/pm8001/pm8001_sas.h |1 + 2 files changed, 432 insertions(+), 25 deletions(-) diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index e8a983f..95b6966 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -163,24 +163,33 @@ static void pm8001_free(struct pm8001_hba_info *pm8001_ha) } #ifdef PM8001_USE_TASKLET + +/** + * tasklet for 64 msi-x interrupt handler + * @opaque: the passed general host adapter struct + * Note: pm8001_tasklet is common for pm8001 & pm80xx + */ static void pm8001_tasklet(unsigned long opaque) { struct pm8001_hba_info *pm8001_ha; + u32 vec; pm8001_ha = (struct pm8001_hba_info *)opaque; if (unlikely(!pm8001_ha)) BUG_ON(1); - PM8001_CHIP_DISP->isr(pm8001_ha, 0); + vec = pm8001_ha->int_vector; + PM8001_CHIP_DISP->isr(pm8001_ha, vec); } #endif +/** + * pm8001_interrupt_handler_x -main interrupt handler invokde for all interrupt. + * It obtains the vector number and calls the equivalent bottom half or services + * directly. + * @vec: vector number; will be 0 for none msi-x operation + * @opaque: the passed general host adapter struct + */ - /** - * pm8001_interrupt - when HBA originate a interrupt,we should invoke this - * dispatcher to handle each case. - * @irq: irq number. - * @opaque: the passed general host adapter struct - */ -static irqreturn_t pm8001_interrupt(int irq, void *opaque) +static inline irqreturn_t pm8001_interrupt_handler_x(int vec, void *opaque) { struct pm8001_hba_info *pm8001_ha; irqreturn_t ret = IRQ_HANDLED; @@ -190,6 +199,7 @@ static irqreturn_t pm8001_interrupt(int irq, void *opaque) return IRQ_NONE; if (!PM8001_CHIP_DISP->is_our_interupt(pm8001_ha)) return IRQ_NONE; + pm8001_ha->int_vector = vec; #ifdef PM8001_USE_TASKLET tasklet_schedule(&pm8001_ha->tasklet); #else @@ -198,6 +208,365 @@ static irqreturn_t pm8001_interrupt(int irq, void *opaque) return ret; } +/* 64 interrupt handlers for 64 msi-x vectors */ +static irqreturn_t pm8001_interrupt_handler0(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(0, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler1(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(1, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler2(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(2, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler3(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(3, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler4(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(4, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler5(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(5, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler6(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(6, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler7(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(7, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler8(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(8, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler9(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(9, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler10(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(10, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler11(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(11, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler12(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(12, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler13(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(13, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler14(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(14, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler15(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(15, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler16(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(16, dev_id); +} + +static irqreturn_t pm8001_interrupt_handler17(int irq, void *dev_id) +{ + return pm8001_interrupt_handler_x(17, dev_id); +} + +static irqretur
[PATCH V2 03/12] pm80xx: Multiple inbound/outbound queue configuration
>From f0b469f372f1c1faa393123f4a3a5e93e05b8387 Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Wed, 27 Feb 2013 20:25:25 +0530 Subject: [PATCH V2 03/12] 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 Ack-by: Jack Wang --- 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 100644 --- 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 100644 --- 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].v
[PATCH V2 02/12] pm80xx: Added SPCv/ve specific ids, variables and modify for SPC
>From ef678e2188866af926f2a089719c24ec99e4e88c Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Wed, 27 Feb 2013 20:22:50 +0530 Subject: [PATCH V2 02/12] pm80xx: Added SPCv/ve specific ids, variables and modify for SPC Updated pci id table with device, vendor, subdevice and subvendor ids for 8081, 8088, 8089 SAS/SATA controllers. Added SPCv/ve related macros. Updated macros, hba info structure and other structures for SPCv/ve. Update of structure and variable names for SPC hardware functionalities. Signed-off-by: Sakthivel K Signed-off-by: Anand Kumar S Ack-by: Jack Wang --- drivers/scsi/pm8001/pm8001_ctl.c | 69 ++--- drivers/scsi/pm8001/pm8001_defs.h | 19 +++- drivers/scsi/pm8001/pm8001_hwi.c | 210 ++--- drivers/scsi/pm8001/pm8001_init.c | 52 - drivers/scsi/pm8001/pm8001_sas.h | 93 ++-- 5 files changed, 324 insertions(+), 119 deletions(-) diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c index 45bc197..ae2b124 100644 --- 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) + );
[PATCH V2 01/12] pm80xx: fix for memory region free
>From 700bfe79294e9f9e1a5def178af52b13928902a9 Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Mon, 4 Feb 2013 12:10:02 +0530 Subject: [PATCH V2 01/12] 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 Ack-by: Jack Wang --- 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 100644 --- 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 >From 700bfe79294e9f9e1a5def178af52b13928902a9 Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Mon, 4 Feb 2013 12:10:02 +0530 Subject: [PATCH V2 01/12] 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 Ack-by: Jack Wang --- 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 100644 --- 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
[PATCH V2 00/12] Support for PMC 8081/8088/8089 controllers
Hi, This is second resubmission for PM8081/88/89 patchset. This handles comments from James Bottomley and Hannes. >From 375653061c0db3189e9e5678b11291b7b0195ac3 Mon Sep 17 00:00:00 2001 From: Sakthivel K Date: Wed, 13 Mar 2013 14:09:48 +0530 Subject: [PATCH V2 00/12] Support for PMC 8081/8088/8089 controllers Patchset V2 Resubmission of patchset addressing Hannes comment 1. Patch5 - Implemented a single tasklet to handle all MSI-x interrupts Patchset V1 Resubmission of pm8001 patchset based on James Bottomley comments 1. The patch permission level corrected to 644. 2. Patches 2 3 and 4 of the original patchset have been merged to a single patch (patch 2) to fix compilation error and ensure individual functionality. 3. Email id's changed to resolvable ids. Sakthivel K (12): pm80xx: fix for memory region free pm80xx: Added SPCv/ve specific ids, variables and modify 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 and relavent 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 | 699 ++- drivers/scsi/pm8001/pm8001_sas.c | 105 +- drivers/scsi/pm8001/pm8001_sas.h | 174 ++- drivers/scsi/pm8001/pm80xx_hwi.c | 4131 + drivers/scsi/pm8001/pm80xx_hwi.h | 1524 ++ 10 files changed, 7163 insertions(+), 385 deletions(-) create mode 100644 drivers/scsi/pm8001/pm80xx_hwi.c create mode 100644 drivers/scsi/pm8001/pm80xx_hwi.h -- 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: [RFC 00/11] Add support for iSCSI Extentions for RDMA (ISER) target
On 08/03/2013 03:45, Nicholas A. Bellinger wrote: This series is first RFC for iSCSI Extentions for RDMA (ISER) target support with existing iscsi-target TCP based socket code for a future v3.10 merge. This code is available in git here: git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending.git iser_target-rfcv1 Ths includes a basic iscsit_transport API that allows different transports to reside under a single iscsi-target configfs control plane, using an pre-defined network portal attribute to enable a rdma_cm listener on top of existing ipoib portals. Hi Nic, Here are quick few nits (...) which need to be sorted out for the next version, I've picked them from running the patches through checkpatch and sparse / gcc warnings checks target-pending]# git format-patch -o /tmp/lio-iser-rfc 7b745c84a9f4ad62db4b67053fbceb5d706451af.. /tmp/lio-iser-rfc/0001-iscsi-target-Add-iscsit_transport-API-template.patch /tmp/lio-iser-rfc/0002-iscsi-target-Initial-traditional-TCP-conversion-to-i.patch /tmp/lio-iser-rfc/0003-iscsi-target-Add-iser-target-parameter-keys-setup-du.patch /tmp/lio-iser-rfc/0004-iscsi-target-Add-per-transport-iscsi_cmd-alloc-free.patch /tmp/lio-iser-rfc/0005-iscsi-target-Refactor-RX-PDU-logic-export-request-PD.patch /tmp/lio-iser-rfc/0006-iscsi-target-Refactor-TX-queue-logic-export-response.patch /tmp/lio-iser-rfc/0007-iscsi-target-Add-iser-network-portal-attribute.patch /tmp/lio-iser-rfc/0008-iser-target-Add-base-proto-includes.patch /tmp/lio-iser-rfc/0009-iser-target-Add-logic-for-verbs.patch /tmp/lio-iser-rfc/0010-iser-target-Add-logic-for-core.patch /tmp/lio-iser-rfc/0011-iser-target-Add-Makefile-Kconfig.patch target-pending]# ./scripts/checkpatch.pl --strict /tmp/lio-iser-rfc/* | grep total total: 0 errors, 8 warnings, 0 checks, 142 lines checked total: 1 errors, 14 warnings, 6 checks, 1097 lines checked total: 0 errors, 15 warnings, 7 checks, 299 lines checked total: 0 errors, 0 warnings, 0 checks, 106 lines checked total: 0 errors, 13 warnings, 4 checks, 795 lines checked total: 1 errors, 12 warnings, 2 checks, 877 lines checked total: 0 errors, 5 warnings, 0 checks, 83 lines checked total: 7 errors, 12 warnings, 1 checks, 170 lines checked total: 1 errors, 9 warnings, 14 checks, 481 lines checked total: 1 errors, 39 warnings, 43 checks, 1732 lines checked total: 0 errors, 0 warnings, 0 checks, 21 lines checked drivers/infiniband/ulp/isert/isert_core.c:774:1: warning: symbol 'isert_dump_ib_wc' was not declared. Should it be static? drivers/infiniband/ulp/isert/isert_verbs.c:341:1: warning: symbol 'isert_put_conn' was not declared. Should it be static? drivers/infiniband/ulp/isert/isert_verbs.c:375:1: warning: symbol 'isert_cma_handler' was not declared. Should it be static? drivers/infiniband/ulp/isert/isert_verbs.c:416:1: warning: symbol 'isert_post_recv' was not declared. Should it be static? drivers/infiniband/ulp/isert/isert_verbs.c:451:1: warning: symbol 'isert_post_send' was not declared. Should it be static? drivers/infiniband/ulp/isert/isert_core.c: In function ?isert_rx_do_work?: drivers/infiniband/ulp/isert/isert_core.c:481: warning: variable ?rc? set but not used Or. -- 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