IB/hfi1: Bug fixes post destaging of driver
Subsystems (2)
cover IB/hfi1: Bug fixes post destaging of driver
Here are a few more bug fixes, most of these are in the lower levels of the driver. There are some coccinelle fix-ups as well.
This series will apply on the patch to move the driver out of staging and should apply cleanly to the hfi1 branch of Doug's GitHub.
I have also staged these in my GitHub tree at:
https://github.com/ddalessa/kernel/tree/for-4.6.
---
Dean Luick (12):
IB/hfi1: Remove ASIC block clear
IB/hfi1: Add shared ASIC structure
IB/hfi1: Add ASIC resource reservation functions IB/hfi1: Change EPROM handling to use resource reservation IB/hfi1: Change SBus handling to use resource reservation IB/hfi1: Change QSFP functions to use resource reservation IB/hfi1: Change thermal init to use resource reservation IB/hfi1: Remove unused HFI1_DO_INIT_ASIC flag IB/hfi1: Reduce hardware mutex timeout
IB/hfi1: Hold i2c resource across debugfs open/close IB/hfi1: Add ASIC flag view/clear
IB/hfi1: Add adaptive cacheless verbs copy
Harish Chegondi (3):
IB/hfi1: Add the break statement that was removed in an earlier patch IB/hfi1: Move constant to the right in bitwise operations IB/hfi1: Replace kmalloc and memcpy with a kmemdup
Jubin John (1):
IB/hfi1: Handle host handshake timeout
Kaike Wan (1):
IB/hfi1: Don't call cond_resched in atomic mode when sending packets
drivers/infiniband/hw/hfi1/chip.c | 172 ++++++++--------------- drivers/infiniband/hw/hfi1/chip.h | 39 +++++ drivers/infiniband/hw/hfi1/debugfs.c | 248 ++++++++++++++++++++++++++++++++- drivers/infiniband/hw/hfi1/efivar.c | 3 drivers/infiniband/hw/hfi1/eprom.c | 36 ++--- drivers/infiniband/hw/hfi1/firmware.c | 238 +++++++++++++++++++++++++++++--- drivers/infiniband/hw/hfi1/hfi.h | 24 +++ drivers/infiniband/hw/hfi1/init.c | 27 +++- drivers/infiniband/hw/hfi1/pcie.c | 13 +- drivers/infiniband/hw/hfi1/pio.c | 4 - drivers/infiniband/hw/hfi1/platform.c | 26 ++- drivers/infiniband/hw/hfi1/qsfp.c | 108 ++++++++++---- drivers/infiniband/hw/hfi1/qsfp.h | 4 + drivers/infiniband/hw/hfi1/rc.c | 2 drivers/infiniband/hw/hfi1/ruc.c | 8 + drivers/infiniband/hw/hfi1/verbs.c | 185 ++++++++++++++++++++++++- drivers/infiniband/hw/hfi1/verbs.h | 22 +++ 17 files changed, 934 insertions(+), 225 deletions(-)
Signature · 5 lines
-Denny -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
A message that is not in the archive (sent off-list or not yet received): 20160305164725.32025.99686.stgit-9QXIwq+3FY+1XWohqUldA0EOCMrvLtNR@public.gmane.org
PATCH 1/17 IB/hfi1: Add the break statement that was removed in an earlier patch
From: Harish Chegondi <[email protected]>
The break statement was unintentionally removed in this patch commit 41ca419abc0ca7ee65d765408cdc1a7fed2897a3 ("staging/rdma/hfi1: Remove hfi1 MR and hfi1 specific qp type")
--- drivers/infiniband/hw/hfi1/ruc.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
drivers/infiniband/hw/hfi1/ruc.c +1 -0
@@ -470,6 +470,7 @@ again: goto inv_err; do_write:if (wqe->length ==0 ) +break ; if (unlikely(!rvt_rkey_ok(qp, &qp->r_sge.sge, wqe->length, wqe->rdma_wr.remote_addr, wqe->rdma_wr.rkey,
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 2/17 IB/hfi1: Move constant to the right in bitwise operations
In reply to a message not in the archiveFrom: Harish Chegondi <[email protected]>
Implement changes recommended by the Coccinelle tool to move constant to the right in bitwise operations
-bash-4.2$ make coccicheck MODE=report M=drivers/infiniband/hw/hfi1/
drivers/infiniband/hw/hfi1/pio.c:765:4-16: Move constant to right. drivers/infiniband/hw/hfi1/rc.c:2503:19-29: Move constant to right. drivers/infiniband/hw/hfi1/chip.c:9813:11-22: Move constant to right. drivers/infiniband/hw/hfi1/chip.c:14468:29-40: Move constant to right.
--- drivers/infiniband/hw/hfi1/chip.c | 6 +++--- drivers/infiniband/hw/hfi1/pio.c | 4 ++-- drivers/infiniband/hw/hfi1/rc.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-)
drivers/infiniband/hw/hfi1/chip.c +3 -3
@@ -9810,7 +9810,7 @@ static int goto_offline(struct hfi1_pportdata *ppd, u8 rem_reason)if (do_transition) { ret =set_physical_link_state (dd, -PLS_OFFLINE | (rem_reason <<8 )); + (rem_reason <<8 ) |PLS_OFFLINE );if (ret !=HCMD_SUCCESS ) { dd_dev_err(dd,
@@ -14465,8 +14465,8 @@ static void handle_temp_err(struct hfi1_devdata *dd)*/ ppd->driver_link_ready =0 ; ppd->link_enabled =0 ; -set_physical_link_state (dd,PLS_OFFLINE | - (OPA_LINKDOWN_REASON_SMA_DISABLED <<8 )); +set_physical_link_state (dd, (OPA_LINKDOWN_REASON_SMA_DISABLED <<8 ) | +PLS_OFFLINE );/* * Step 2: Shutdown LCB and 8051 * After shutdown, do not restore DC_CFG_RESET value.
drivers/infiniband/hw/hfi1/pio.c +2 -2
@@ -762,8 +762,8 @@ struct send_context *sc_alloc(struct hfi1_devdata *dd, int type,/* set the default partition key */ write_kctxt_csr (dd, hw_context,SC (CHECK_PARTITION_KEY ), - (DEFAULT_PKEY & -SC (CHECK_PARTITION_KEY_VALUE_MASK )) << + (SC (CHECK_PARTITION_KEY_VALUE_MASK ) & +DEFAULT_PKEY ) <<SC (CHECK_PARTITION_KEY_VALUE_SHIFT ));/* per context type checks */
drivers/infiniband/hw/hfi1/rc.c +1 -1
@@ -2500,7 +2500,7 @@ send_last:return ; rnr_nak: - qp->r_nak_state =IB_RNR_NAK | qp->r_min_rnr_timer; + qp->r_nak_state = qp->r_min_rnr_timer |IB_RNR_NAK ; qp->r_ack_psn = qp->r_psn;/* Queue RNR NAK for later */ rc_defered_ack (rcd, qp);
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 3/17 IB/hfi1: Replace kmalloc and memcpy with a kmemdup
In reply to a message not in the archiveFrom: Harish Chegondi <[email protected]>
This change was recommended by Coccinelle tool when I ran the command:
-bash-4.2$ make coccicheck MODE=patch M=drivers/infiniband/hw/hfi1/
--- drivers/infiniband/hw/hfi1/efivar.c | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-)
drivers/infiniband/hw/hfi1/efivar.c +1 -2
@@ -125,13 +125,12 @@ static int read_efi_var(const char *name, unsigned long *size,* temporary buffer. Now allocate a correctly sized * buffer. */ - data =kmalloc (temp_size,GFP_KERNEL ); + data =kmemdup (temp_buffer, temp_size,GFP_KERNEL );if (!data) { ret = -ENOMEM ; goto fail; } -memcpy (data, temp_buffer, temp_size); *size = temp_size; *return_data = data;
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 4/17 IB/hfi1: Remove ASIC block clear
In reply to a message not in the archiveFrom: Dean Luick <[email protected]>
The ASIC block is shared between two HFIs. Individual devices should not initialize registers there. Retain the power-on values. Individual users set registers as needed with one exception. Clear sbus fast mode on "slow" calls.
--- drivers/infiniband/hw/hfi1/chip.c | 88 --------------------------------- drivers/infiniband/hw/hfi1/firmware.c | 3 + 2 files changed, 3 insertions(+), 88 deletions(-)
drivers/infiniband/hw/hfi1/chip.c +0 -88
@@ -12934,91 +12934,6 @@ static void reset_cce_csrs(struct hfi1_devdata *dd)write_csr (dd,CCE_INT_COUNTER_ARRAY32 + (8 * i),0 ); } -/* set ASIC CSRs to chip reset defaults */ -static void reset_asic_csrs (struct hfi1_devdata *dd) -{ -int i; - -/* -* If the HFIs are shared between separate nodes or VMs, -* then more will need to be done here. One idea is a module -* parameter that returns early, letting the first power-on or -* a known first load do the reset and blocking all others. -*/ - -if (!(dd->flags &HFI1_DO_INIT_ASIC )) -return ; - -if (dd->icode !=ICODE_FPGA_EMULATION ) { -/* emulation does not have an SBus - leave these alone */ -/* -* All writes to ASIC_CFG_SBUS_REQUEST do something. -* Notes: -* o The reset is not zero if aimed at the core. See the -* SBus documentation for details. -* o If the SBus firmware has been updated (e.g. by the BIOS), -* will the reset revert that? -*/ -/* ASIC_CFG_SBUS_REQUEST leave alone */ -write_csr (dd,ASIC_CFG_SBUS_EXECUTE ,0 ); - } -/* ASIC_SBUS_RESULT read-only */ -write_csr (dd,ASIC_STS_SBUS_COUNTERS ,0 ); -for (i =0 ; i <ASIC_NUM_SCRATCH ; i++) -write_csr (dd,ASIC_CFG_SCRATCH + (8 * i),0 ); -write_csr (dd,ASIC_CFG_MUTEX ,0 );/* this will clear it */ - -/* We might want to retain this state across FLR if we ever use it */ -write_csr (dd,ASIC_CFG_DRV_STR ,0 ); - -/* ASIC_CFG_THERM_POLL_EN leave alone */ -/* ASIC_STS_THERM read-only */ -/* ASIC_CFG_RESET leave alone */ - -write_csr (dd,ASIC_PCIE_SD_HOST_CMD ,0 ); -/* ASIC_PCIE_SD_HOST_STATUS read-only */ -write_csr (dd,ASIC_PCIE_SD_INTRPT_DATA_CODE ,0 ); -write_csr (dd,ASIC_PCIE_SD_INTRPT_ENABLE ,0 ); -/* ASIC_PCIE_SD_INTRPT_PROGRESS read-only */ -write_csr (dd,ASIC_PCIE_SD_INTRPT_STATUS , ~0ull );/* clear */ -/* ASIC_HFI0_PCIE_SD_INTRPT_RSPD_DATA read-only */ -/* ASIC_HFI1_PCIE_SD_INTRPT_RSPD_DATA read-only */ -for (i =0 ; i <16 ; i++) -write_csr (dd,ASIC_PCIE_SD_INTRPT_LIST + (8 * i),0 ); - -/* ASIC_GPIO_IN read-only */ -write_csr (dd,ASIC_GPIO_OE ,0 ); -write_csr (dd,ASIC_GPIO_INVERT ,0 ); -write_csr (dd,ASIC_GPIO_OUT ,0 ); -write_csr (dd,ASIC_GPIO_MASK ,0 ); -/* ASIC_GPIO_STATUS read-only */ -write_csr (dd,ASIC_GPIO_CLEAR , ~0ull ); -/* ASIC_GPIO_FORCE leave alone */ - -/* ASIC_QSFP1_IN read-only */ -write_csr (dd,ASIC_QSFP1_OE ,0 ); -write_csr (dd,ASIC_QSFP1_INVERT ,0 ); -write_csr (dd,ASIC_QSFP1_OUT ,0 ); -write_csr (dd,ASIC_QSFP1_MASK ,0 ); -/* ASIC_QSFP1_STATUS read-only */ -write_csr (dd,ASIC_QSFP1_CLEAR , ~0ull ); -/* ASIC_QSFP1_FORCE leave alone */ - -/* ASIC_QSFP2_IN read-only */ -write_csr (dd,ASIC_QSFP2_OE ,0 ); -write_csr (dd,ASIC_QSFP2_INVERT ,0 ); -write_csr (dd,ASIC_QSFP2_OUT ,0 ); -write_csr (dd,ASIC_QSFP2_MASK ,0 ); -/* ASIC_QSFP2_STATUS read-only */ -write_csr (dd,ASIC_QSFP2_CLEAR , ~0ull ); -/* ASIC_QSFP2_FORCE leave alone */ - -write_csr (dd,ASIC_EEP_CTL_STAT ,ASIC_EEP_CTL_STAT_RESETCSR ); -/* this also writes a NOP command, clearing paging mode */ -write_csr (dd,ASIC_EEP_ADDR_CMD ,0 ); -write_csr (dd,ASIC_EEP_DATA ,0 ); -} -/* set MISC CSRs to chip reset defaults */ static void reset_misc_csrs (struct hfi1_devdata *dd) {
@@ -13428,14 +13343,11 @@ static void init_chip(struct hfi1_devdata *dd)hfi1_pcie_flr (dd);restore_pci_variables (dd); } - -reset_asic_csrs (dd); }else {dd_dev_info (dd,"Resetting CSRs with writes\n" );reset_cce_csrs (dd);reset_txe_csrs (dd);reset_rxe_csrs (dd); -reset_asic_csrs (dd);reset_misc_csrs (dd); }/* clear the DC reset */
drivers/infiniband/hw/hfi1/firmware.c +3 -0
@@ -1170,6 +1170,9 @@ int sbus_request_slow(struct hfi1_devdata *dd, {u64 reg, count =0 ; +/* make sure fast mode is clear */ +clear_sbus_fast_mode (dd); +sbus_request (dd, receiver_addr, data_addr, command, data_in);write_csr (dd,ASIC_CFG_SBUS_EXECUTE ,ASIC_CFG_SBUS_EXECUTE_EXECUTE_SMASK );
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 5/17 IB/hfi1: Add shared ASIC structure
In reply to a message not in the archiveFrom: Dean Luick <[email protected]>
Create a shared structure to exist between devices that share the same ASIC.
--- drivers/infiniband/hw/hfi1/chip.c | 28 +++++++++++++++++++++++++--- drivers/infiniband/hw/hfi1/hfi.h | 9 +++++++++ drivers/infiniband/hw/hfi1/init.c | 20 ++++++++++++++++++++ 3 files changed, 54 insertions(+), 3 deletions(-)
drivers/infiniband/hw/hfi1/chip.c +25 -3
@@ -13800,15 +13800,20 @@ void hfi1_start_cleanup(struct hfi1_devdata *dd) ((dev)->base_guid & ~(1ULL <<GUID_HFI_INDEX_SHIFT ))/* +* Information can be shared between the two HFIs on the same ASIC +* in the same OS. This function finds the peer device and sets +* up a shared structure. +* * Certain chip functions need to be initialized only once per asic * instead of per-device. This function finds the peer device and * checks whether that chip initialization needs to be done by this * device. */ -static void asic_should_init (struct hfi1_devdata *dd) +static int init_asic_data (struct hfi1_devdata *dd) {unsigned long flags;struct hfi1_devdata *tmp, *peer =NULL ; +int ret =0 ;spin_lock_irqsave (&hfi1_devs_lock, flags);/* Find our peer device */
@@ -13826,7 +13831,22 @@ static void asic_should_init(struct hfi1_devdata *dd)*/ if (!peer || !(peer->flags &HFI1_DO_INIT_ASIC )) dd->flags |=HFI1_DO_INIT_ASIC ; + +if (peer) { + dd->asic_data = peer->asic_data; + }else { + dd->asic_data =kzalloc (sizeof (*dd->asic_data),GFP_KERNEL ); +if (!dd->asic_data) { + ret = -ENOMEM ; + goto done; + } +mutex_init (&dd->asic_data->asic_resource_mutex); + } + dd->asic_data->dds[dd->hfi1_id] = dd;/* self back-pointer */ + +done:spin_unlock_irqrestore (&hfi1_devs_lock, flags); +return ret; }/*
@@ -14076,8 +14096,10 @@ struct hfi1_devdata *hfi1_init_dd(struct pci_dev *pdev,/* needs to be done before we look for the peer device */ read_guid (dd); -/* should this device init the ASIC block? */ -asic_should_init (dd); +/* set up shared ASIC data with peer device */ + ret =init_asic_data (dd); +if (ret) + goto bail_cleanup;/* obtain chip sizes, reset chip CSRs */ init_chip (dd);
drivers/infiniband/hw/hfi1/hfi.h +9 -0
@@ -805,6 +805,12 @@ struct hfi1_temp {u8 triggers;/* temperature triggers */ }; +/* common data between shared ASIC HFIs */ +struct hfi1_asic_data { +struct hfi1_devdata *dds[2 ];/* back pointers */ +struct mutex asic_resource_mutex; +}; +/* device data struct now contains only "general per-device" info. * fields related to a physical IB port are in a hfi1_pportdata struct. */
@@ -880,6 +886,9 @@ struct hfi1_devdata {wait_queue_head_t sdma_unfreeze_wq;atomic_t sdma_unfreeze_count; +/* common data between shared ASIC HFIs in this OS */ +struct hfi1_asic_data *asic_data; +/* hfi1_pportdata, points to array of (physical) port-specific * data structs, indexed by pidx (0..n-1) */
drivers/infiniband/hw/hfi1/init.c +20 -0
@@ -974,6 +974,25 @@ void hfi1_free_ctxtdata(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd)kfree (rcd); } +/* +* Release our hold on the shared asic data. If we are the last one, +* free the structure. Must be holding hfi1_devs_lock. +*/ +static void release_asic_data (struct hfi1_devdata *dd) +{ +int other; + +if (!dd->asic_data) +return ; + dd->asic_data->dds[dd->hfi1_id] =NULL ; + other = dd->hfi1_id ?0 :1 ; +if (!dd->asic_data->dds[other]) { +/* we are the last holder, free it */ +kfree (dd->asic_data); + } + dd->asic_data =NULL ; +} +void hfi1_free_devdata (struct hfi1_devdata *dd) {unsigned long flags;
@@ -981,6 +1000,7 @@ void hfi1_free_devdata(struct hfi1_devdata *dd)spin_lock_irqsave (&hfi1_devs_lock, flags);idr_remove (&hfi1_unit_table, dd->unit);list_del (&dd->list); +release_asic_data (dd);spin_unlock_irqrestore (&hfi1_devs_lock, flags);free_platform_config (dd);rcu_barrier ();/* wait for rcu callbacks to complete */
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 6/17 IB/hfi1: Add ASIC resource reservation functions
In reply to a message not in the archiveFrom: Dean Luick <[email protected]>
The ASIC block is a shared hardware resource between two devices on the chip. Add functions to acquire and release these resources in a way that is safe for both multiple users on the same OS and multiple users on different OSes, while holding the hardware mutex as little as possible.
Reservations are noted in a scratch register in the shared region. There are two types of reservations: per-HFI dynamic and permanent.
--- drivers/infiniband/hw/hfi1/chip.c | 2 drivers/infiniband/hw/hfi1/chip.h | 30 +++++ drivers/infiniband/hw/hfi1/firmware.c | 187 +++++++++++++++++++++++++++++++++ 3 files changed, 219 insertions(+), 0 deletions(-)
drivers/infiniband/hw/hfi1/chip.c +2 -0
@@ -13368,6 +13368,7 @@ static void init_chip(struct hfi1_devdata *dd)*/ write_csr (dd,ASIC_QSFP1_OUT ,0x1f );write_csr (dd,ASIC_QSFP2_OUT ,0x1f ); +init_chip_resources (dd); }static void init_early_variables (struct hfi1_devdata *dd)
@@ -13794,6 +13795,7 @@ void hfi1_start_cleanup(struct hfi1_devdata *dd)free_cntrs (dd);free_rcverr (dd);clean_up_interrupts (dd); +finish_chip_resources (dd); }#define HFI_BASE_GUID (dev) \
drivers/infiniband/hw/hfi1/chip.h +30 -0
@@ -639,6 +639,36 @@ int load_firmware(struct hfi1_devdata *dd);void dispose_firmware (void );int acquire_hw_mutex (struct hfi1_devdata *dd);void release_hw_mutex (struct hfi1_devdata *dd); + +/* +* Bitmask of dynamic access for ASIC block chip resources. Each HFI has its +* own range of bits for the resource so it can clear its own bits on +* starting and exiting. If either HFI has the resource bit set, the +* resource is in use. The separate bit ranges are: +* HFI0 bits 7:0 +* HFI1 bits 15:8 +*/ +#define CR_SBUS 0x01/* SBUS, THERM, and PCIE registers */ +#define CR_EPROM 0x02/* EEP, GPIO registers */ +#define CR_I2C1 0x04/* QSFP1_OE register */ +#define CR_I2C2 0x08/* QSFP2_OE register */ +#define CR_DYN_SHIFT 8/* dynamic flag shift */ +#define CR_DYN_MASK ((1ull << CR_DYN_SHIFT) - 1) + +/* +* Bitmask of static ASIC states these are outside of the dynamic ASIC +* block chip resources above. These are to be set once and never cleared. +* Must be holding the SBus dynamic flag when setting. +*/ +#define CR_THERM_INIT 0x010000 + +int acquire_chip_resource (struct hfi1_devdata *dd,u32 resource,u32 mswait); +void release_chip_resource (struct hfi1_devdata *dd,u32 resource); +bool check_chip_resource (struct hfi1_devdata *dd,u32 resource, +const char *func); +void init_chip_resources (struct hfi1_devdata *dd); +void finish_chip_resources (struct hfi1_devdata *dd); +void fabric_serdes_reset (struct hfi1_devdata *dd);int read_8051_data (struct hfi1_devdata *dd,u32 addr,u32 len,u64 *result);
drivers/infiniband/hw/hfi1/firmware.c +187 -0
193 lines not on this page · raw message
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 7/17 IB/hfi1: Change EPROM handling to use resource reservation
In reply to a message not in the archiveFrom: Dean Luick <[email protected]>
Change EPROM handling to use the new ASIC resource reservation system.
--- drivers/infiniband/hw/hfi1/eprom.c | 36 +++++++++++++----------------------- 1 files changed, 13 insertions(+), 23 deletions(-)
drivers/infiniband/hw/hfi1/eprom.c +13 -23
@@ -102,9 +102,11 @@#define EPROM_WP_N BIT_ULL(14)/* EPROM write line */ /* -* Use the EP mutex to guard against other callers from within the driver. +* How long to wait for the EPROM to become available, in ms. +* The spec 32 Mb EPROM takes around 40s to erase then write. +* Double it for safety. */ -static DEFINE_MUTEX (eprom_mutex); +#define EPROM_TIMEOUT 80000/* ms */ /* * Turn on external enable line that allows writing on the flash.
@@ -371,14 +373,9 @@ int handle_eprom_command(struct file *fp, const struct hfi1_cmd *cmd)if (!dd->eprom_available)return -EOPNOTSUPP ; -/* lock against other callers touching the ASIC block */ -mutex_lock (&eprom_mutex); - -/* lock against the other HFI on another OS */ - ret =acquire_hw_mutex (dd); + ret =acquire_chip_resource (dd,CR_EPROM ,EPROM_TIMEOUT );if (ret) { -dd_dev_err (dd, -"%s: unable to acquire hw mutex, no EPROM support\n" , +dd_dev_err (dd,"%s: unable to acquire EPROM resource\n" , __func__); goto done_asic; }
@@ -428,9 +425,8 @@ int handle_eprom_command(struct file *fp, const struct hfi1_cmd *cmd)break ; } -release_hw_mutex (dd); +release_chip_resource (dd,CR_EPROM ); done_asic: -mutex_unlock (&eprom_mutex);return ret; }
@@ -441,23 +437,18 @@ int eprom_init(struct hfi1_devdata *dd) {int ret =0 ; -/* only the discrete chip has an EPROM, nothing to do */ +/* only the discrete chip has an EPROM */ if (dd->pcidev->device !=PCI_DEVICE_ID_INTEL0 )return 0 ; -/* lock against other callers */ -mutex_lock (&eprom_mutex); -/* -* Lock against the other HFI on another OS - the mutex above -* would have caught anything in this driver. It is OK if -* both OSes reset the EPROM - as long as they don't do it at -* the same time. +* It is OK if both HFIs reset the EPROM as long as they don't +* do it at the same time. */ - ret =acquire_hw_mutex (dd); + ret =acquire_chip_resource (dd,CR_EPROM ,EPROM_TIMEOUT );if (ret) {dd_dev_err (dd, -"%s: unable to acquire hw mutex, no EPROM support\n" , +"%s: unable to acquire EPROM resource, no EPROM support\n" , __func__); goto done_asic; }
@@ -474,8 +465,7 @@ int eprom_init(struct hfi1_devdata *dd)write_csr (dd,ASIC_EEP_ADDR_CMD ,CMD_RELEASE_POWERDOWN_NOID ); dd->eprom_available = true; -release_hw_mutex (dd); +release_chip_resource (dd,CR_EPROM ); done_asic: -mutex_unlock (&eprom_mutex);return ret; }
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 8/17 IB/hfi1: Change SBus handling to use resource reservation
In reply to a message not in the archiveFrom: Dean Luick <[email protected]>
The SBus resource includes SBUS, PCIE, and THERM registers. Change SBus handling to use the new ASIC resource reservation system.
--- drivers/infiniband/hw/hfi1/chip.c | 9 +++++- drivers/infiniband/hw/hfi1/chip.h | 3 ++ drivers/infiniband/hw/hfi1/firmware.c | 46 +++++++++++++++++---------------- drivers/infiniband/hw/hfi1/pcie.c | 13 ++++++--- 4 files changed, 42 insertions(+), 29 deletions(-)
drivers/infiniband/hw/hfi1/chip.c +7 -2
@@ -14324,7 +14324,12 @@ static int thermal_init(struct hfi1_devdata *dd) !(dd->flags & HFI1_DO_INIT_ASIC))return ret; -acquire_hw_mutex (dd); + ret =acquire_chip_resource (dd,CR_SBUS ,SBUS_TIMEOUT ); +if (ret) { +THERM_FAILURE (dd, ret,"Acquire SBus" ); +return ret; + } +dd_dev_info (dd,"Initializing thermal sensor\n" );/* Disable polling of thermal readings */ write_csr (dd,ASIC_CFG_THERM_POLL_EN ,0x0 );
@@ -14372,7 +14377,7 @@ static int thermal_init(struct hfi1_devdata *dd)/* Enable polling of thermal readings */ write_csr (dd,ASIC_CFG_THERM_POLL_EN ,0x1 ); done: -release_hw_mutex (dd); +release_chip_resource (dd,CR_SBUS );return ret; }
drivers/infiniband/hw/hfi1/chip.h +3 -0
@@ -669,6 +669,9 @@ bool check_chip_resource(struct hfi1_devdata *dd, u32 resource,void init_chip_resources (struct hfi1_devdata *dd);void finish_chip_resources (struct hfi1_devdata *dd); +/* ms wait time for access to an SBus resoure */ +#define SBUS_TIMEOUT 4000/* long enough for a FW download and SBR */ +void fabric_serdes_reset (struct hfi1_devdata *dd);int read_8051_data (struct hfi1_devdata *dd,u32 addr,u32 len,u64 *result);
drivers/infiniband/hw/hfi1/firmware.c +24 -22
86 lines not on this page · raw message
drivers/infiniband/hw/hfi1/pcie.c +8 -5
@@ -773,7 +773,7 @@ static int load_eq_table(struct hfi1_devdata *dd, const u8 eq[11][3], u8 fs,/* * Steps to be done after the PCIe firmware is downloaded and * before the SBR for the Pcie Gen3. -* The hardware mutex is already being held. +* The SBus resource is already being held. */ static void pcie_post_steps (struct hfi1_devdata *dd) {
@@ -1012,10 +1012,13 @@ int do_pcie_gen3_transition(struct hfi1_devdata *dd) goto done_no_mutex; } -/* hold the HW mutex across the firmware download and SBR */ - ret =acquire_hw_mutex (dd); -if (ret) +/* hold the SBus resource across the firmware download and SBR */ + ret =acquire_chip_resource (dd,CR_SBUS ,SBUS_TIMEOUT ); +if (ret) { +dd_dev_err (dd,"%s: unable to acquire SBus resource\n" , + __func__);return ret; + }/* make sure thermal polling is not causing interrupts */ therm =read_csr (dd,ASIC_CFG_THERM_POLL_EN );
@@ -1324,7 +1327,7 @@ done:dd_dev_info (dd,"%s: Re-enable therm polling\n" , __func__); } -release_hw_mutex (dd); +release_chip_resource (dd,CR_SBUS ); done_no_mutex:/* return no error if it is OK to be at current speed */ if (ret && !return_error) {
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 9/17 IB/hfi1: Change QSFP functions to use resource reservation
In reply to a message not in the archiveFrom: Dean Luick <[email protected]>
Remove the mutex guarding each operation in favor the ASIC resource acquire/release. Push the resource acquire/release, above each operation call to allow exclusive access across multiple operations.
--- drivers/infiniband/hw/hfi1/chip.c | 20 +++++- drivers/infiniband/hw/hfi1/chip.h | 3 + drivers/infiniband/hw/hfi1/debugfs.c | 22 +++++-- drivers/infiniband/hw/hfi1/hfi.h | 14 ++++ drivers/infiniband/hw/hfi1/init.c | 1 drivers/infiniband/hw/hfi1/platform.c | 26 ++++++-- drivers/infiniband/hw/hfi1/qsfp.c | 108 ++++++++++++++++++++++----------- drivers/infiniband/hw/hfi1/qsfp.h | 4 + 8 files changed, 142 insertions(+), 56 deletions(-)
drivers/infiniband/hw/hfi1/chip.c +15 -5
@@ -6267,8 +6267,8 @@ void handle_8051_request(struct work_struct *work) cdr_ctrl_byte &= ~(1 << i); } } -qsfp_write (ppd, ppd->dd->hfi1_id,QSFP_CDR_CTRL_BYTE_OFFS , - &cdr_ctrl_byte,1 ); +one_qsfp_write (ppd, dd->hfi1_id,QSFP_CDR_CTRL_BYTE_OFFS , + &cdr_ctrl_byte,1 );hreq_response (dd,HREQ_SUCCESS , data);refresh_qsfp_cache (ppd, &ppd->qsfp_info);break ;
@@ -9290,8 +9290,8 @@ void qsfp_event(struct work_struct *work)if (qd->check_interrupt_flags) {u8 qsfp_interrupt_status[16 ] = {0 ,}; -if (qsfp_read (ppd, dd->hfi1_id,6 , - &qsfp_interrupt_status[0 ],16 ) !=16 ) { +if (one_qsfp_read (ppd, dd->hfi1_id,6 , + &qsfp_interrupt_status[0 ],16 ) !=16 ) {dd_dev_info (dd,"%s: Failed to read status of QSFP module\n" , __func__);
@@ -9845,7 +9845,17 @@ static int goto_offline(struct hfi1_pportdata *ppd, u8 rem_reason)if (ppd->port_type ==PORT_TYPE_QSFP && ppd->qsfp_info.limiting_active &&qsfp_mod_present (ppd)) { -set_qsfp_tx (ppd,0 ); +int ret; + + ret =acquire_chip_resource (dd,qsfp_resource (dd),QSFP_WAIT ); +if (ret ==0 ) { +set_qsfp_tx (ppd,0 ); +release_chip_resource (dd,qsfp_resource (dd)); + }else { +/* not fatal, but should warn */ +dd_dev_err (dd, +"Unable to acquire lock to turn off QSFP TX\n" ); + } }/*
drivers/infiniband/hw/hfi1/chip.h +3 -0
@@ -672,6 +672,9 @@ void finish_chip_resources(struct hfi1_devdata *dd);/* ms wait time for access to an SBus resoure */ #define SBUS_TIMEOUT 4000/* long enough for a FW download and SBR */ +/* ms wait time for a qsfp (i2c) chain to become available */ +#define QSFP_WAIT 20000/* long enough for FW update to the F4 uc */ +void fabric_serdes_reset (struct hfi1_devdata *dd);int read_8051_data (struct hfi1_devdata *dd,u32 addr,u32 len,u64 *result);
drivers/infiniband/hw/hfi1/debugfs.c +17 -5
@@ -465,16 +465,22 @@ static ssize_t __i2c_debugfs_write(struct file *file, const char __user *buf, goto _free; } + ret =acquire_chip_resource (ppd->dd,i2c_target (target),0 ); +if (ret) + goto _free; + total_written =i2c_write (ppd, target, i2c_addr, offset, buff, count);if (total_written <0 ) { ret = total_written; - goto _free; + goto _release; } *ppos += total_written; ret = total_written; + _release: +release_chip_resource (ppd->dd,i2c_target (target)); _free:kfree (buff); _return:
@@ -526,10 +532,14 @@ static ssize_t __i2c_debugfs_read(struct file *file, char __user *buf, goto _return; } + ret =acquire_chip_resource (ppd->dd,i2c_target (target),0 ); +if (ret) + goto _free; + total_read =i2c_read (ppd, target, i2c_addr, offset, buff, count);if (total_read <0 ) { ret = total_read; - goto _free; + goto _release; } *ppos += total_read;
@@ -537,11 +547,13 @@ static ssize_t __i2c_debugfs_read(struct file *file, char __user *buf, ret =copy_to_user (buf, buff, total_read);if (ret >0 ) { ret = -EFAULT ; - goto _free; + goto _release; } ret = total_read; + _release: +release_chip_resource (ppd->dd,i2c_target (target)); _free:kfree (buff); _return:
@@ -592,7 +604,7 @@ static ssize_t __qsfp_debugfs_write(struct file *file, const char __user *buf, goto _free; } - total_written =qsfp_write (ppd, target, *ppos, buff, count); + total_written =one_qsfp_write (ppd, target, *ppos, buff, count);if (total_written <0 ) { ret = total_written; goto _free;
@@ -646,7 +658,7 @@ static ssize_t __qsfp_debugfs_read(struct file *file, char __user *buf, goto _return; } - total_read =qsfp_read (ppd, target, *ppos, buff, count); + total_read =one_qsfp_read (ppd, target, *ppos, buff, count);if (total_read <0 ) { ret = total_read; goto _free;
drivers/infiniband/hw/hfi1/hfi.h +12 -2
@@ -1048,8 +1048,6 @@ struct hfi1_devdata {struct platform_config platform_config;struct platform_config_cache pcfg_cache; -/* control high-level access to qsfp */ -struct mutex qsfp_i2c_mutex;struct diag_client *diag_client;spinlock_t hfi1_diag_trans_lock;/* protect diag observer ops */
@@ -1938,6 +1936,18 @@ static inline void setextled(struct hfi1_devdata *dd, u32 on) write_csr(dd, DCC_CFG_LED_CNTRL, 0x10); } +/* return the i2c resource given the target */ +static inline u32 i2c_target (u32 target) +{ +return target ?CR_I2C2 :CR_I2C1 ; +} + +/* return the i2c chain chip resource that this HFI uses for QSFP */ +static inline u32 qsfp_resource (struct hfi1_devdata *dd) +{ +return i2c_target (dd->hfi1_id); +} +int hfi1_tempsense_rd (struct hfi1_devdata *dd,struct hfi1_temp *temp);#endif /* _HFI1_KERNEL_H */
drivers/infiniband/hw/hfi1/init.c +0 -1
@@ -1065,7 +1065,6 @@ struct hfi1_devdata *hfi1_alloc_devdata(struct pci_dev *pdev, size_t extra)spin_lock_init (&dd->sc_init_lock);spin_lock_init (&dd->dc8051_lock);spin_lock_init (&dd->dc8051_memlock); -mutex_init (&dd->qsfp_i2c_mutex);seqlock_init (&dd->sc2vl_lock);spin_lock_init (&dd->sde_map_lock);spin_lock_init (&dd->pio_map_lock);
drivers/infiniband/hw/hfi1/platform.c +18 -8
@@ -601,23 +601,30 @@ static void apply_tunings(static int tune_active_qsfp (struct hfi1_pportdata *ppd,u32 *ptr_tx_preset,u32 *ptr_rx_preset,u32 *ptr_total_atten) { -int ret =0 ; +int ret;u16 lss = ppd->link_speed_supported, lse = ppd->link_speed_enabled;u8 *cache = ppd->qsfp_info.cache; + ret =acquire_chip_resource (ppd->dd,qsfp_resource (ppd->dd),QSFP_WAIT ); +if (ret) { +dd_dev_err (ppd->dd,"%s: hfi%d: cannot lock i2c chain\n" , + __func__, (int )ppd->dd->hfi1_id); +return ret; + } + ppd->qsfp_info.limiting_active =1 ; ret =set_qsfp_tx (ppd,0 );if (ret) -return ret; + goto bail_unlock; ret =qual_power (ppd);if (ret) -return ret; + goto bail_unlock; ret =qual_bitrate (ppd);if (ret) -return ret; + goto bail_unlock;if (ppd->qsfp_info.reset_needed) {reset_qsfp (ppd);
@@ -629,7 +636,7 @@ static int tune_active_qsfp(struct hfi1_pportdata *ppd, u32 *ptr_tx_preset, ret =set_qsfp_high_power (ppd);if (ret) -return ret; + goto bail_unlock;if (cache[QSFP_EQ_INFO_OFFS ] &0x4 ) { ret = get_platform_config_field(
@@ -639,7 +646,7 @@ static int tune_active_qsfp(struct hfi1_pportdata *ppd, u32 *ptr_tx_preset, ptr_tx_preset, 4);if (ret) { *ptr_tx_preset =OPA_INVALID_INDEX ; -return ret; + goto bail_unlock; } }else { ret = get_platform_config_field(
@@ -649,7 +656,7 @@ static int tune_active_qsfp(struct hfi1_pportdata *ppd, u32 *ptr_tx_preset, ptr_tx_preset, 4);if (ret) { *ptr_tx_preset =OPA_INVALID_INDEX ; -return ret; + goto bail_unlock; } }
@@ -658,7 +665,7 @@ static int tune_active_qsfp(struct hfi1_pportdata *ppd, u32 *ptr_tx_preset, PORT_TABLE_RX_PRESET_IDX, ptr_rx_preset, 4);if (ret) { *ptr_rx_preset =OPA_INVALID_INDEX ; -return ret; + goto bail_unlock; }if ((lss &OPA_LINK_SPEED_25G ) && (lse &OPA_LINK_SPEED_25G ))
@@ -677,6 +684,9 @@ static int tune_active_qsfp(struct hfi1_pportdata *ppd, u32 *ptr_tx_preset,apply_rx_amplitude_settings (ppd, *ptr_rx_preset, *ptr_tx_preset); ret =set_qsfp_tx (ppd,1 ); + +bail_unlock: +release_chip_resource (ppd->dd,qsfp_resource (ppd->dd));return ret; }
drivers/infiniband/hw/hfi1/qsfp.c +73 -35
230 lines not on this page · raw message
drivers/infiniband/hw/hfi1/qsfp.h +4 -0
@@ -235,3 +235,7 @@ int qsfp_write(struct hfi1_pportdata *ppd, u32 target, int addr, void *bp, int len);int qsfp_read (struct hfi1_pportdata *ppd,u32 target,int addr,void *bp,int len); +int one_qsfp_write (struct hfi1_pportdata *ppd,u32 target,int addr,void *bp, +int len); +int one_qsfp_read (struct hfi1_pportdata *ppd,u32 target,int addr,void *bp, +int len);
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 10/17 IB/hfi1: Change thermal init to use resource reservation
In reply to a message not in the archiveFrom: Dean Luick <[email protected]>
Use the resource reservation system to flag that the ASIC thermal has been initialized.
--- drivers/infiniband/hw/hfi1/chip.c | 8 +++++++- 1 files changed, 7 insertions(+), 1 deletions(-)
drivers/infiniband/hw/hfi1/chip.c +7 -1
@@ -14331,7 +14331,7 @@ static int thermal_init(struct hfi1_devdata *dd)int ret =0 ;if (dd->icode !=ICODE_RTL_SILICON || - !(dd->flags &HFI1_DO_INIT_ASIC )) +check_chip_resource (dd,CR_THERM_INIT ,NULL ))return ret; ret =acquire_chip_resource (dd,CR_SBUS ,SBUS_TIMEOUT );
@@ -14386,6 +14386,12 @@ static int thermal_init(struct hfi1_devdata *dd)/* Enable polling of thermal readings */ write_csr (dd,ASIC_CFG_THERM_POLL_EN ,0x1 ); + +/* Set initialized flag */ + ret =acquire_chip_resource (dd,CR_THERM_INIT ,0 ); +if (ret) +THERM_FAILURE (dd, ret,"Unable to set thermal init flag" ); + done:release_chip_resource (dd,CR_SBUS );return ret;
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 11/17 IB/hfi1: Remove unused HFI1_DO_INIT_ASIC flag
In reply to a message not in the archiveFrom: Dean Luick <[email protected]>
The flag HFI1_DO_INIT_ASIC flag is no longer used. Remove the flag and the code that sets it.
--- drivers/infiniband/hw/hfi1/chip.c | 12 ------------ drivers/infiniband/hw/hfi1/hfi.h | 1 - 2 files changed, 0 insertions(+), 13 deletions(-)
drivers/infiniband/hw/hfi1/chip.c +0 -12
@@ -13815,11 +13815,6 @@ void hfi1_start_cleanup(struct hfi1_devdata *dd)* Information can be shared between the two HFIs on the same ASIC * in the same OS. This function finds the peer device and sets * up a shared structure. -* -* Certain chip functions need to be initialized only once per asic -* instead of per-device. This function finds the peer device and -* checks whether that chip initialization needs to be done by this -* device. */ static int init_asic_data (struct hfi1_devdata *dd) {
@@ -13837,13 +13832,6 @@ static int init_asic_data(struct hfi1_devdata *dd) } } -/* -* "Claim" the ASIC for initialization if it hasn't been -" "claimed" yet. -*/ -if (!peer || !(peer->flags &HFI1_DO_INIT_ASIC )) - dd->flags |=HFI1_DO_INIT_ASIC ; -if (peer) { dd->asic_data = peer->asic_data; }else {
drivers/infiniband/hw/hfi1/hfi.h +0 -1
@@ -1602,7 +1602,6 @@ static inline struct cc_state *get_cc_state(struct hfi1_pportdata *ppd)#define HFI1_HAS_SDMA_TIMEOUT 0x8#define HFI1_HAS_SEND_DMA 0x10/* Supports Send DMA */ #define HFI1_FORCED_FREEZE 0x80/* driver forced freeze mode */ -#define HFI1_DO_INIT_ASIC 0x100/* This device will init the ASIC */ /* IB dword length mask in PBC (lower 11 bits); same for all chips */ #define HFI1_PBC_LENGTH_MASK ((1 << 11) - 1)
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 12/17 IB/hfi1: Reduce hardware mutex timeout
In reply to a message not in the archiveFrom: Dean Luick <[email protected]>
The hardware mutex is now held only long enough to set or clear flags. Reduce the timeout to something more reasonable.
--- drivers/infiniband/hw/hfi1/firmware.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/infiniband/hw/hfi1/firmware.c +1 -1
@@ -198,7 +198,7 @@ static const struct firmware *platform_config;#define RSA_ENGINE_TIMEOUT 100/* ms */ /* hardware mutex timeout, in ms */ -#define HM_TIMEOUT 4000/* 4 s */ +#define HM_TIMEOUT 10/* ms */ /* 8051 memory access timeout, in us */ #define DC8051_ACCESS_TIMEOUT 100/* us */
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 13/17 IB/hfi1: Hold i2c resource across debugfs open/close
In reply to a message not in the archiveFrom: Dean Luick <[email protected]>
External i2c firmware updates are done in multiple steps and cannot have other things done in between. For debugfs files, acquire the resource on open and release it on close.
--- drivers/infiniband/hw/hfi1/debugfs.c | 145 +++++++++++++++++++++++++++++----- 1 files changed, 124 insertions(+), 21 deletions(-)
drivers/infiniband/hw/hfi1/debugfs.c +124 -21
@@ -49,6 +49,7 @@#include <linux/seq_file.h> #include <linux/kernel.h> #include <linux/export.h> +#include <linux/module.h> #include "hfi.h" #include "debugfs.h"
@@ -465,22 +466,16 @@ static ssize_t __i2c_debugfs_write(struct file *file, const char __user *buf, goto _free; } - ret =acquire_chip_resource (ppd->dd,i2c_target (target),0 ); -if (ret) - goto _free; - total_written =i2c_write (ppd, target, i2c_addr, offset, buff, count);if (total_written <0 ) { ret = total_written; - goto _release; + goto _free; } *ppos += total_written; ret = total_written; - _release: -release_chip_resource (ppd->dd,i2c_target (target)); _free:kfree (buff); _return:
@@ -532,14 +527,10 @@ static ssize_t __i2c_debugfs_read(struct file *file, char __user *buf, goto _return; } - ret =acquire_chip_resource (ppd->dd,i2c_target (target),0 ); -if (ret) - goto _free; - total_read =i2c_read (ppd, target, i2c_addr, offset, buff, count);if (total_read <0 ) { ret = total_read; - goto _release; + goto _free; } *ppos += total_read;
@@ -547,13 +538,11 @@ static ssize_t __i2c_debugfs_read(struct file *file, char __user *buf, ret =copy_to_user (buf, buff, total_read);if (ret >0 ) { ret = -EFAULT ; - goto _release; + goto _free; } ret = total_read; - _release: -release_chip_resource (ppd->dd,i2c_target (target)); _free:kfree (buff); _return:
@@ -604,7 +593,7 @@ static ssize_t __qsfp_debugfs_write(struct file *file, const char __user *buf, goto _free; } - total_written =one_qsfp_write (ppd, target, *ppos, buff, count); + total_written =qsfp_write (ppd, target, *ppos, buff, count);if (total_written <0 ) { ret = total_written; goto _free;
@@ -658,7 +647,7 @@ static ssize_t __qsfp_debugfs_read(struct file *file, char __user *buf, goto _return; } - total_read =one_qsfp_read (ppd, target, *ppos, buff, count); + total_read =qsfp_read (ppd, target, *ppos, buff, count);if (total_read <0 ) { ret = total_read; goto _free;
@@ -695,6 +684,104 @@ static ssize_t qsfp2_debugfs_read(struct file *file, char __user *buf,return __qsfp_debugfs_read (file, buf, count, ppos,1 ); } +static int __i2c_debugfs_open (struct inode *in,struct file *fp,u32 target) +{ +struct hfi1_pportdata *ppd; +int ret; + +if (!try_module_get (THIS_MODULE )) +return -ENODEV ; + + ppd =private2ppd (fp); + + ret =acquire_chip_resource (ppd->dd,i2c_target (target),0 ); +if (ret)/* failed - release the module */ +module_put (THIS_MODULE ); + +return ret; +} + +static int i2c1_debugfs_open (struct inode *in,struct file *fp) +{ +return __i2c_debugfs_open (in, fp,0 ); +} + +static int i2c2_debugfs_open (struct inode *in,struct file *fp) +{ +return __i2c_debugfs_open (in, fp,1 ); +} + +static int __i2c_debugfs_release (struct inode *in,struct file *fp,u32 target) +{ +struct hfi1_pportdata *ppd; + + ppd =private2ppd (fp); + +release_chip_resource (ppd->dd,i2c_target (target)); +module_put (THIS_MODULE ); + +return 0 ; +} + +static int i2c1_debugfs_release (struct inode *in,struct file *fp) +{ +return __i2c_debugfs_release (in, fp,0 ); +} + +static int i2c2_debugfs_release (struct inode *in,struct file *fp) +{ +return __i2c_debugfs_release (in, fp,1 ); +} + +static int __qsfp_debugfs_open (struct inode *in,struct file *fp,u32 target) +{ +struct hfi1_pportdata *ppd; +int ret; + +if (!try_module_get (THIS_MODULE )) +return -ENODEV ; + + ppd =private2ppd (fp); + + ret =acquire_chip_resource (ppd->dd,i2c_target (target),0 ); +if (ret)/* failed - release the module */ +module_put (THIS_MODULE ); + +return ret; +} + +static int qsfp1_debugfs_open (struct inode *in,struct file *fp) +{ +return __qsfp_debugfs_open (in, fp,0 ); +} + +static int qsfp2_debugfs_open (struct inode *in,struct file *fp) +{ +return __qsfp_debugfs_open (in, fp,1 ); +} + +static int __qsfp_debugfs_release (struct inode *in,struct file *fp,u32 target) +{ +struct hfi1_pportdata *ppd; + + ppd =private2ppd (fp); + +release_chip_resource (ppd->dd,i2c_target (target)); +module_put (THIS_MODULE ); + +return 0 ; +} + +static int qsfp1_debugfs_release (struct inode *in,struct file *fp) +{ +return __qsfp_debugfs_release (in, fp,0 ); +} + +static int qsfp2_debugfs_release (struct inode *in,struct file *fp) +{ +return __qsfp_debugfs_release (in, fp,1 ); +} +#define DEBUGFS_OPS (nm, readroutine, writeroutine) \ { \ .name = nm, \
@@ -705,6 +792,18 @@ static ssize_t qsfp2_debugfs_read(struct file *file, char __user *buf, }, \ } +#define DEBUGFS_XOPS (nm, readf, writef, openf, releasef) \ +{ \ + .name = nm, \ + .ops = { \ + .read = readf, \ + .write = writef, \ + .llseek = generic_file_llseek, \ + .open = openf, \ + .release = releasef \ + }, \ +} +static const struct counter_info cntr_ops[] = {DEBUGFS_OPS ("counter_names" , dev_names_read,NULL ),DEBUGFS_OPS ("counters" , dev_counters_read,NULL ),
@@ -713,11 +812,15 @@ static const struct counter_info cntr_ops[] = {static const struct counter_info port_cntr_ops[] = {DEBUGFS_OPS ("port%dcounters" , portcntrs_debugfs_read,NULL ), -DEBUGFS_OPS ("i2c1" , i2c1_debugfs_read, i2c1_debugfs_write), -DEBUGFS_OPS ("i2c2" , i2c2_debugfs_read, i2c2_debugfs_write), +DEBUGFS_XOPS ("i2c1" , i2c1_debugfs_read, i2c1_debugfs_write, + i2c1_debugfs_open, i2c1_debugfs_release), +DEBUGFS_XOPS ("i2c2" , i2c2_debugfs_read, i2c2_debugfs_write, + i2c2_debugfs_open, i2c2_debugfs_release),DEBUGFS_OPS ("qsfp_dump%d" , qsfp_debugfs_dump,NULL ), -DEBUGFS_OPS ("qsfp1" , qsfp1_debugfs_read, qsfp1_debugfs_write), -DEBUGFS_OPS ("qsfp2" , qsfp2_debugfs_read, qsfp2_debugfs_write), +DEBUGFS_XOPS ("qsfp1" , qsfp1_debugfs_read, qsfp1_debugfs_write, + qsfp1_debugfs_open, qsfp1_debugfs_release), +DEBUGFS_XOPS ("qsfp2" , qsfp2_debugfs_read, qsfp2_debugfs_write, + qsfp2_debugfs_open, qsfp2_debugfs_release), };void hfi1_dbg_ibdev_init (struct hfi1_ibdev *ibd)
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 14/17 IB/hfi1: Add ASIC flag view/clear
In reply to a message not in the archiveFrom: Dean Luick <[email protected]>
Different OSes using parts of the same hardware may leave cross-device flags set. Export a debugfs file to view and clear these flags if needed.
--- drivers/infiniband/hw/hfi1/debugfs.c | 125 ++++++++++++++++++++++++++++++++++ 1 files changed, 125 insertions(+), 0 deletions(-)
drivers/infiniband/hw/hfi1/debugfs.c +125 -0
@@ -404,6 +404,130 @@ static ssize_t portcntrs_debugfs_read(struct file *file, char __user *buf,return rval; } +static void check_dyn_flag (u64 scratch0,char *p,int size,int *used, +int this_hfi,int hfi,u32 flag,const char *what) +{ +u32 mask; + + mask = flag << (hfi ?CR_DYN_SHIFT :0 ); +if (scratch0 & mask) { + *used +=scnprintf (p + *used, size - *used, +" 0x%08x - HFI%d %s in use, %s device\n" , + mask, hfi, what, + this_hfi == hfi ?"this" :"other" ); + } +} + +static ssize_t asic_flags_read (struct file *file,char __user *buf, +size_t count,loff_t *ppos) +{ +struct hfi1_pportdata *ppd; +struct hfi1_devdata *dd; +u64 scratch0; +char *tmp; +int ret =0 ; +int size; +int used; +int i; + +rcu_read_lock (); + ppd =private2ppd (file); + dd = ppd->dd; + size =PAGE_SIZE ; + used =0 ; + tmp =kmalloc (size,GFP_KERNEL ); +if (!tmp) { +rcu_read_unlock (); +return -ENOMEM ; + } + + scratch0 =read_csr (dd,ASIC_CFG_SCRATCH ); + used +=scnprintf (tmp + used, size - used, +"Resource flags: 0x%016llx\n" , scratch0); + +/* check permanent flag */ +if (scratch0 &CR_THERM_INIT ) { + used +=scnprintf (tmp + used, size - used, +" 0x%08x - thermal monitoring initialized\n" , + (u32 )CR_THERM_INIT ); + } + +/* check each dynamic flag on each HFI */ +for (i =0 ; i <2 ; i++) { +check_dyn_flag (scratch0, tmp, size, &used, dd->hfi1_id, i, +CR_SBUS ,"SBus" ); +check_dyn_flag (scratch0, tmp, size, &used, dd->hfi1_id, i, +CR_EPROM ,"EPROM" ); +check_dyn_flag (scratch0, tmp, size, &used, dd->hfi1_id, i, +CR_I2C1 ,"i2c chain 1" ); +check_dyn_flag (scratch0, tmp, size, &used, dd->hfi1_id, i, +CR_I2C2 ,"i2c chain 2" ); + } + used +=scnprintf (tmp + used, size - used,"Write bits to clear\n" ); + + ret =simple_read_from_buffer (buf, count, ppos, tmp, used); +rcu_read_unlock (); +kfree (tmp); +return ret; +} + +static ssize_t asic_flags_write (struct file *file,const char __user *buf, +size_t count,loff_t *ppos) +{ +struct hfi1_pportdata *ppd; +struct hfi1_devdata *dd; +char *buff; +int ret; +unsigned long long value; +u64 scratch0; +u64 clear; + +rcu_read_lock (); + ppd =private2ppd (file); + dd = ppd->dd; + + buff =kmalloc (count +1 ,GFP_KERNEL ); +if (!buff) { + ret = -ENOMEM ; + goto do_return; + } + + ret =copy_from_user (buff, buf, count); +if (ret >0 ) { + ret = -EFAULT ; + goto do_free; + } + +/* zero terminate and read the expected integer */ + buff[count] =0 ; + ret =kstrtoull (buff,0 , &value); +if (ret) + goto do_free; + clear = value; + +/* obtain exclusive access */ +mutex_lock (&dd->asic_data->asic_resource_mutex); +acquire_hw_mutex (dd); + + scratch0 =read_csr (dd,ASIC_CFG_SCRATCH ); + scratch0 &= ~clear; +write_csr (dd,ASIC_CFG_SCRATCH , scratch0); +/* force write to be visible to other HFI on another OS */ + (void )read_csr (dd,ASIC_CFG_SCRATCH ); + +release_hw_mutex (dd); +mutex_unlock (&dd->asic_data->asic_resource_mutex); + +/* return the number of bytes written */ + ret = count; + + do_free: +kfree (buff); + do_return: +rcu_read_unlock (); +return ret; +} +/* * read the per-port QSFP data for ppd */
@@ -821,6 +945,7 @@ static const struct counter_info port_cntr_ops[] = { qsfp1_debugfs_open, qsfp1_debugfs_release), DEBUGFS_XOPS("qsfp2", qsfp2_debugfs_read, qsfp2_debugfs_write, qsfp2_debugfs_open, qsfp2_debugfs_release), + DEBUGFS_OPS("asic_flags", asic_flags_read, asic_flags_write), };void hfi1_dbg_ibdev_init (struct hfi1_ibdev *ibd)
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 15/17 IB/hfi1: Handle host handshake timeout
In reply to a message not in the archiveFrom: Jubin John <[email protected]>
Host handshake timeout can occur during the verify capability state. This is a LNI related failure and should be handled in the same way as other LNI failures.
--- drivers/infiniband/hw/hfi1/chip.c | 3 ++- drivers/infiniband/hw/hfi1/chip.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-)
drivers/infiniband/hw/hfi1/chip.c +2 -1
@@ -963,7 +963,8 @@ static struct flag_table dc8051_info_err_flags[] = {FLAG_ENTRY0 ("Failed LNI(OptEq)" ,FAILED_LNI_OPTEQ ),FLAG_ENTRY0 ("Failed LNI(VerifyCap_1)" ,FAILED_LNI_VERIFY_CAP1 ),FLAG_ENTRY0 ("Failed LNI(VerifyCap_2)" ,FAILED_LNI_VERIFY_CAP2 ), - FLAG_ENTRY0("Failed LNI(ConfigLT)", FAILED_LNI_CONFIGLT) +FLAG_ENTRY0 ("Failed LNI(ConfigLT)" ,FAILED_LNI_CONFIGLT ), + FLAG_ENTRY0("Host Handshake Timeout", HOST_HANDSHAKE_TIMEOUT) };/*
drivers/infiniband/hw/hfi1/chip.h +2 -1
@@ -253,12 +253,13 @@#define FAILED_LNI_VERIFY_CAP1 BIT(9)#define FAILED_LNI_VERIFY_CAP2 BIT(10)#define FAILED_LNI_CONFIGLT BIT(11) +#define HOST_HANDSHAKE_TIMEOUT BIT(12)#define FAILED_LNI (FAILED_LNI_POLLING | FAILED_LNI_DEBOUNCE \ | FAILED_LNI_ESTBCOMM | FAILED_LNI_OPTEQ \ | FAILED_LNI_VERIFY_CAP1 \ | FAILED_LNI_VERIFY_CAP2 \ - | FAILED_LNI_CONFIGLT) + | FAILED_LNI_CONFIGLT | HOST_HANDSHAKE_TIMEOUT)/* DC_DC8051_DBG_ERR_INFO_SET_BY_8051.HOST_MSG - host message flags */ #define HOST_REQ_DONE BIT(0)
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 16/17 IB/hfi1: Add adaptive cacheless verbs copy
In reply to a message not in the archiveFrom: Dean Luick <[email protected]>
The kernel memcpy is faster than a cacheless copy. However, if too much of the L3 cache is overwritten by one-time copies then overall bandwidth suffers. Implement an adaptive scheme where full page copies are tracked and if the number of unique entries are larger than a threshold, verbs will use a cacheless copy. Tracked entries are gradually cleaned, allowing memcpy to resume once the larger copies have stopped.
--- drivers/infiniband/hw/hfi1/init.c | 6 + drivers/infiniband/hw/hfi1/verbs.c | 185 ++++++++++++++++++++++++++++++++++++ drivers/infiniband/hw/hfi1/verbs.h | 22 ++++ 3 files changed, 211 insertions(+), 2 deletions(-)
drivers/infiniband/hw/hfi1/init.c +6 -0
@@ -1242,6 +1242,9 @@ static int __init hfi1_mod_init(void)idr_init (&hfi1_unit_table);hfi1_dbg_init (); + ret =hfi1_wss_init (); +if (ret <0 ) + goto bail_wss; ret =pci_register_driver (&hfi1_pci_driver);if (ret <0 ) {pr_err ("Unable to register driver: error %d\n" , -ret);
@@ -1250,6 +1253,8 @@ static int __init hfi1_mod_init(void) goto bail;/* all OK */ bail_dev: +hfi1_wss_exit (); +bail_wss:hfi1_dbg_exit ();idr_destroy (&hfi1_unit_table);dev_cleanup ();
@@ -1265,6 +1270,7 @@ module_init(hfi1_mod_init); static void __exit hfi1_mod_cleanup(void) {pci_unregister_driver (&hfi1_pci_driver); +hfi1_wss_exit ();hfi1_dbg_exit (); hfi1_cpulist_count =0 ;kfree (hfi1_cpulist);
drivers/infiniband/hw/hfi1/verbs.c +183 -2
212 lines not on this page · raw message
drivers/infiniband/hw/hfi1/verbs.h +22 -0
@@ -475,6 +475,28 @@ int hfi1_verbs_send_dma(struct rvt_qp *qp, struct hfi1_pkt_state *ps,int hfi1_verbs_send_pio (struct rvt_qp *qp,struct hfi1_pkt_state *ps,u64 pbc); +int hfi1_wss_init (void ); +void hfi1_wss_exit (void ); + +/* platform specific: return the lowest level cache (llc) size, in KiB */ +static inline int wss_llc_size (void ) +{ +/* assume that the boot CPU value is universal for all CPUs */ +return boot_cpu_data.x86_cache_size; +} + +/* platform specific: cacheless copy */ +static inline void cacheless_memcpy (void *dst,void *src,size_t n) +{ +/* +* Use the only available X64 cacheless copy. Add a __user cast +* to quiet sparse. The src agument is already in the kernel so +* there are no security issues. The extra fault recovery machinery +* is not invoked. +*/ +__copy_user_nocache (dst, (void __user *)src, n,0 ); +} +extern const enum ib_wc_opcode ib_hfi1_wc_opcode[];extern const u8 hdr_len_by_opcode[];
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 17/17 IB/hfi1: Don't call cond_resched in atomic mode when sending packets
In reply to a message not in the archiveFrom: Kaike Wan <[email protected]>
This patch fixed the problem where the driver might reschedule in atomic mode when sending packets. This is due to the fact that the call to cond_resched() in hfi1_do_send() might occur in atomic mode and a check is required to avoid the warning message:
"kernel: BUG: scheduling while atomic: swapper/2/0/0x10000100."
--- drivers/infiniband/hw/hfi1/ruc.c | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-)
drivers/infiniband/hw/hfi1/ruc.c +5 -2
@@ -906,8 +906,11 @@ void hfi1_do_send(struct rvt_qp *qp) *ps.ppd->dd->send_schedule);return ; } -cond_resched (); -this_cpu_inc (*ps.ppd->dd->send_schedule); +if (!irqs_disabled ()) { +cond_resched (); +this_cpu_inc ( + *ps.ppd->dd->send_schedule); + } timeout = jiffies + (timeout_int) /8 ; }spin_lock_irqsave (&qp->s_lock, flags);
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html