Compare commits

...

8 Commits

Author SHA1 Message Date
monkeyyang f1620d1768 HZ1000
Signed-off-by: monkeyyang <monkeyyang@tencent.com>
2021-05-14 16:54:12 +08:00
MengEn 6a3d84a0e8 net: fix compile error in 9db1459215
there is a compile error in 9db1459215 fix it

Signed-off-by: mengensun<mengensun@tencent.com>
Reviewed-by: kaixuxia<kaixuxia@tencent.com>
2021-04-22 09:05:23 +00:00
MengEn 9db1459215 pv4: fix race condition between route lookup and
invalidation

[upstream commit] 5018c59607a511cdee743b629c76206d9c9e6d7b

ipv4: fix race condition between route lookup and invalidation

Jesse and Ido reported the following race condition:
<CPU A, t0> - Received packet A is forwarded and cached dst entry is
taken from the nexthop ('nhc->nhc_rth_input'). Calls skb_dst_set()

<t1> - Given Jesse has busy routers ("ingesting full BGP routing tables
from multiple ISPs"), route is added / deleted and rt_cache_flush() is
called

<CPU B, t2> - Received packet B tries to use the same cached dst entry
from t0, but rt_cache_valid() is no longer true and it is replaced in
rt_cache_route() by the newer one. This calls dst_dev_put() on the
original dst entry which assigns the blackhole netdev to 'dst->dev'

<CPU A, t3> - dst_input(skb) is called on packet A and it is dropped due
to 'dst->dev' being the blackhole netdev

There are 2 issues in the v4 routing code:
1. A per-netns counter is used to do the validation of the route. That
means whenever a route is changed in the netns, users of all routes in
the netns needs to redo lookup. v6 has an implementation of only
updating fn_sernum for routes that are affected.
2. When rt_cache_valid() returns false, rt_cache_route() is called to
throw away the current cache, and create a new one. This seems
unnecessary because as long as this route does not change, the route
cache does not need to be recreated.

To fully solve the above 2 issues, it probably needs quite some code
changes and requires careful testing, and does not suite for net branch.

So this patch only tries to add the deleted cached rt into the uncached
list, so user could still be able to use it to receive packets until
it's done.

Fixes: 95c47f9cf5e0 ("ipv4: call dst_dev_put() properly")
Signed-off-by: Wei Wang <weiwan@google.com>
Reported-by: Ido Schimmel <idosch@idosch.org>
Reported-by: Jesse Hathaway <jesse@mbuki-mvuki.org>
Tested-by: Jesse Hathaway <jesse@mbuki-mvuki.org>
Acked-by: Martin KaFai Lau <kafai@fb.com>
Cc: David Ahern <dsahern@gmail.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-04-21 06:23:05 +00:00
MengEn eff5c3174b netfilter: x_tables: Use correct memory barriers.
[upstream commit]: 175e476b8cdf2a4de7432583b49c871345e4f8a1
[upstream commit]: cc00bcaa589914096edef7fb87ca5cee4a166b5c
[upstream commit]: d3d40f237480abf3268956daf18cdc56edd32834

When a new table value was assigned, it was followed by a write memory
barrier. This ensured that all writes before this point would complete
before any writes after this point. However, to determine whether the
rules are unused, the sequence counter is read. To ensure that all
writes have been done before these reads, a full memory barrier is
needed, not just a write memory barrier. The same argument applies when
incrementing the counter, before the rules are read.

Changing to using smp_mb() instead of smp_wmb() fixes the kernel panic
reported in cc00bcaa5899 (which is still present), while still
maintaining the same speed of replacing tables.

The smb_mb() barriers potentially slow the packet path, however testing
has shown no measurable change in performance on a 4-core MIPS64
platform.

Fixes: 7f5c6d4f665b ("netfilter: get rid of atomic ops in fast path")
Signed-off-by: Mark Tomlinson <mark.tomlinson@alliedtelesis.co.nz>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2021-04-19 06:16:11 +00:00
MengEn 9d1c23eb89 netfilter: x_tables: don't use seqlock when fetching old counters
[upstream commit]: d13e7b2e65f6dfbe97b845d75741a970181b9fec

netfilter: x_tables: don't use seqlock when fetching old counters

after previous commit xt_replace_table will wait until all cpus
had even seqcount (i.e., no cpu is accessing old ruleset).

Add a 'old' counter retrival version that doesn't synchronize counters.
Its not needed, the old counters are not in use anymore at this point.

This speeds up table replacement on busy systems with large tables
(and many cores).

Cc: Dan Williams <dcbw@redhat.com>
Cc: Eric Dumazet <edumazet@google.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2021-04-19 06:16:11 +00:00
MengEn ccdeb257e0 x_tables: make xt_replace_table wait until old rules are
not used anymore

[upstream commit] 80055dab5de0c8677bc148c4717ddfc753a9148e

xt_replace_table relies on table replacement counter retrieval (which
uses xt_recseq to synchronize pcpu counters).

This is fine, however with large rule set get_counters() can take
a very long time -- it needs to synchronize all counters because
it has to assume concurrent modifications can occur.

Make xt_replace_table synchronize by itself by waiting until all cpus
had an even seqcount.

This allows a followup patch to copy the counters of the old ruleset
without any synchonization after xt_replace_table has completed.

Cc: Dan Williams <dcbw@redhat.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2021-04-19 06:16:11 +00:00
yongduan 985a0aad22 backport wake affine upstream optimization
[upstream]
7332dec0 sched/fair: Only immediately migrate tasks due to interrupts
         if prev and target CPUs share cache
806486c3 sched/fair: Do not migrate if the prev_cpu is idle
082f764a sched/fair: Do not migrate on wake_affine_weight() if weights
         are equal
d8fcb81f sched/fair: Check for idle core in wake_affine

Signed-off-by: yongduan <yongduan@tencent.com>
2021-03-17 17:00:12 +08:00
Kaixu Xia 207a58f198 scsi: smartpqi: update driver version to 1.2.4-070 2021-03-16 14:13:34 +08:00
13 changed files with 2065 additions and 400 deletions

View File

@ -21,6 +21,9 @@
#if !defined(_SMARTPQI_H)
#define _SMARTPQI_H
#include <scsi/scsi_host.h>
#include <linux/bsg-lib.h>
#pragma pack(1)
#define PQI_DEVICE_SIGNATURE "PQI DREG"
@ -97,6 +100,12 @@ struct pqi_ctrl_registers {
struct pqi_device_registers pqi_registers; /* 4000h */
};
#if ((HZ) < 1000)
#define PQI_HZ 1000
#else
#define PQI_HZ (HZ)
#endif
#define PQI_DEVICE_REGISTERS_OFFSET 0x4000
enum pqi_io_path {
@ -347,6 +356,10 @@ struct pqi_event_config {
#define PQI_MAX_EVENT_DESCRIPTORS 255
#define PQI_EVENT_OFA_MEMORY_ALLOCATION 0x0
#define PQI_EVENT_OFA_QUIESCE 0x1
#define PQI_EVENT_OFA_CANCELLED 0x2
struct pqi_event_response {
struct pqi_iu_header header;
u8 event_type;
@ -354,7 +367,17 @@ struct pqi_event_response {
u8 request_acknowlege : 1;
__le16 event_id;
__le32 additional_event_id;
u8 data[16];
union {
struct {
__le32 bytes_requested;
u8 reserved[12];
} ofa_memory_allocation;
struct {
__le16 reason; /* reason for cancellation */
u8 reserved[14];
} ofa_cancelled;
} data;
};
struct pqi_event_acknowledge_request {
@ -389,6 +412,54 @@ struct pqi_task_management_response {
u8 response_code;
};
struct pqi_vendor_general_request {
struct pqi_iu_header header;
__le16 request_id;
__le16 function_code;
union {
struct {
__le16 first_section;
__le16 last_section;
u8 reserved[48];
} config_table_update;
struct {
__le64 buffer_address;
__le32 buffer_length;
u8 reserved[40];
} ofa_memory_allocation;
} data;
};
struct pqi_vendor_general_response {
struct pqi_iu_header header;
__le16 request_id;
__le16 function_code;
__le16 status;
u8 reserved[2];
};
#define PQI_VENDOR_GENERAL_CONFIG_TABLE_UPDATE 0
#define PQI_VENDOR_GENERAL_HOST_MEMORY_UPDATE 1
#define PQI_OFA_VERSION 1
#define PQI_OFA_SIGNATURE "OFA_QRM"
#define PQI_OFA_MAX_SG_DESCRIPTORS 64
#define PQI_OFA_MEMORY_DESCRIPTOR_LENGTH \
(offsetof(struct pqi_ofa_memory, sg_descriptor) + \
(PQI_OFA_MAX_SG_DESCRIPTORS * sizeof(struct pqi_sg_descriptor)))
struct pqi_ofa_memory {
__le64 signature; /* "OFA_QRM" */
__le16 version; /* version of this struct(1 = 1st version) */
u8 reserved[62];
__le32 bytes_allocated; /* total allocated memory in bytes */
__le16 num_memory_descriptors;
u8 reserved1[2];
struct pqi_sg_descriptor sg_descriptor[1];
};
struct pqi_aio_error_info {
u8 status;
u8 service_response;
@ -419,6 +490,7 @@ struct pqi_raid_error_info {
#define PQI_REQUEST_IU_GENERAL_ADMIN 0x60
#define PQI_REQUEST_IU_REPORT_VENDOR_EVENT_CONFIG 0x72
#define PQI_REQUEST_IU_SET_VENDOR_EVENT_CONFIG 0x73
#define PQI_REQUEST_IU_VENDOR_GENERAL 0x75
#define PQI_REQUEST_IU_ACKNOWLEDGE_VENDOR_EVENT 0xf6
#define PQI_RESPONSE_IU_GENERAL_MANAGEMENT 0x81
@ -430,6 +502,7 @@ struct pqi_raid_error_info {
#define PQI_RESPONSE_IU_AIO_PATH_IO_ERROR 0xf3
#define PQI_RESPONSE_IU_AIO_PATH_DISABLED 0xf4
#define PQI_RESPONSE_IU_VENDOR_EVENT 0xf5
#define PQI_RESPONSE_IU_VENDOR_GENERAL 0xf7
#define PQI_GENERAL_ADMIN_FUNCTION_REPORT_DEVICE_CAPABILITY 0x0
#define PQI_GENERAL_ADMIN_FUNCTION_CREATE_IQ 0x10
@ -483,6 +556,8 @@ struct pqi_raid_error_info {
#define CISS_CMD_STATUS_TMF 0xd
#define CISS_CMD_STATUS_AIO_DISABLED 0xe
#define PQI_CMD_STATUS_ABORTED CISS_CMD_STATUS_ABORTED
#define PQI_NUM_EVENT_QUEUE_ELEMENTS 32
#define PQI_EVENT_OQ_ELEMENT_LENGTH sizeof(struct pqi_event_response)
@ -490,6 +565,7 @@ struct pqi_raid_error_info {
#define PQI_EVENT_TYPE_HARDWARE 0x2
#define PQI_EVENT_TYPE_PHYSICAL_DEVICE 0x4
#define PQI_EVENT_TYPE_LOGICAL_DEVICE 0x5
#define PQI_EVENT_TYPE_OFA 0xfb
#define PQI_EVENT_TYPE_AIO_STATE_CHANGE 0xfd
#define PQI_EVENT_TYPE_AIO_CONFIG_CHANGE 0xfe
@ -554,6 +630,7 @@ typedef u32 pqi_index_t;
#define SOP_TASK_ATTRIBUTE_ACA 4
#define SOP_TMF_COMPLETE 0x0
#define SOP_TMF_REJECTED 0x4
#define SOP_TMF_FUNCTION_SUCCEEDED 0x8
/* additional CDB bytes usage field codes */
@ -581,8 +658,8 @@ struct pqi_admin_queues_aligned {
struct pqi_admin_queues {
void *iq_element_array;
void *oq_element_array;
volatile pqi_index_t *iq_ci;
volatile pqi_index_t *oq_pi;
pqi_index_t *iq_ci;
pqi_index_t __iomem *oq_pi;
dma_addr_t iq_element_array_bus_addr;
dma_addr_t oq_element_array_bus_addr;
dma_addr_t iq_ci_bus_addr;
@ -606,8 +683,8 @@ struct pqi_queue_group {
dma_addr_t oq_element_array_bus_addr;
__le32 __iomem *iq_pi[2];
pqi_index_t iq_pi_copy[2];
volatile pqi_index_t *iq_ci[2];
volatile pqi_index_t *oq_pi;
pqi_index_t __iomem *iq_ci[2];
pqi_index_t __iomem *oq_pi;
dma_addr_t iq_ci_bus_addr[2];
dma_addr_t oq_pi_bus_addr;
__le32 __iomem *oq_ci;
@ -620,7 +697,7 @@ struct pqi_event_queue {
u16 oq_id;
u16 int_msg_num;
void *oq_element_array;
volatile pqi_index_t *oq_pi;
pqi_index_t __iomem *oq_pi;
dma_addr_t oq_element_array_bus_addr;
dma_addr_t oq_pi_bus_addr;
__le32 __iomem *oq_ci;
@ -642,11 +719,13 @@ struct pqi_encryption_info {
#define PQI_CONFIG_TABLE_MAX_LENGTH ((u16)~0)
/* configuration table section IDs */
#define PQI_CONFIG_TABLE_ALL_SECTIONS (-1)
#define PQI_CONFIG_TABLE_SECTION_GENERAL_INFO 0
#define PQI_CONFIG_TABLE_SECTION_FIRMWARE_FEATURES 1
#define PQI_CONFIG_TABLE_SECTION_FIRMWARE_ERRATA 2
#define PQI_CONFIG_TABLE_SECTION_DEBUG 3
#define PQI_CONFIG_TABLE_SECTION_HEARTBEAT 4
#define PQI_CONFIG_TABLE_SECTION_SOFT_RESET 5
struct pqi_config_table {
u8 signature[8]; /* "CFGTABLE" */
@ -678,6 +757,18 @@ struct pqi_config_table_general_info {
/* command */
};
struct pqi_config_table_firmware_features {
struct pqi_config_table_section_header header;
__le16 num_elements;
u8 features_supported[];
/* u8 features_requested_by_host[]; */
/* u8 features_enabled[]; */
};
#define PQI_FIRMWARE_FEATURE_OFA 0
#define PQI_FIRMWARE_FEATURE_SMP 1
#define PQI_FIRMWARE_FEATURE_SOFT_RESET_HANDSHAKE 11
struct pqi_config_table_debug {
struct pqi_config_table_section_header header;
__le32 scratchpad;
@ -688,6 +779,22 @@ struct pqi_config_table_heartbeat {
__le32 heartbeat_counter;
};
struct pqi_config_table_soft_reset {
struct pqi_config_table_section_header header;
u8 soft_reset_status;
};
#define PQI_SOFT_RESET_INITIATE 0x1
#define PQI_SOFT_RESET_ABORT 0x2
enum pqi_soft_reset_status {
RESET_INITIATE_FIRMWARE,
RESET_INITIATE_DRIVER,
RESET_ABORT,
RESET_NORESPONSE,
RESET_TIMEDOUT
};
union pqi_reset_register {
struct {
u32 reset_type : 3;
@ -806,8 +913,10 @@ struct pqi_scsi_dev {
u8 scsi3addr[8];
__be64 wwid;
u8 volume_id[16];
u8 unique_id[16];
u8 is_physical_device : 1;
u8 is_external_raid_device : 1;
u8 is_expander_smp_device : 1;
u8 target_lun_valid : 1;
u8 device_gone : 1;
u8 new_device : 1;
@ -815,6 +924,7 @@ struct pqi_scsi_dev {
u8 volume_offline : 1;
bool aio_enabled; /* only valid for physical disks */
bool in_reset;
bool in_remove;
bool device_offline;
u8 vendor[8]; /* bytes 8-15 of inquiry data */
u8 model[16]; /* bytes 16-31 of inquiry data */
@ -852,6 +962,8 @@ struct pqi_scsi_dev {
#define CISS_VPD_LV_DEVICE_GEOMETRY 0xc1 /* vendor-specific page */
#define CISS_VPD_LV_BYPASS_STATUS 0xc2 /* vendor-specific page */
#define CISS_VPD_LV_STATUS 0xc3 /* vendor-specific page */
#define SCSI_VPD_HEADER_SZ 4
#define SCSI_VPD_DEVICE_ID_IDX 8 /* Index of page id in page */
#define VPD_PAGE (1 << 8)
@ -914,6 +1026,7 @@ struct pqi_sas_node {
struct pqi_sas_port {
struct list_head port_list_entry;
u64 sas_address;
struct pqi_scsi_dev *device;
struct sas_port *port;
int next_phy_index;
struct list_head phy_list_head;
@ -945,13 +1058,15 @@ struct pqi_io_request {
struct list_head request_list_entry;
};
#define PQI_NUM_SUPPORTED_EVENTS 6
#define PQI_NUM_SUPPORTED_EVENTS 7
struct pqi_event {
bool pending;
u8 event_type;
__le16 event_id;
__le32 additional_event_id;
__le32 ofa_bytes_requested;
__le16 ofa_cancel_reason;
};
#define PQI_RESERVED_IO_SLOTS_LUN_RESET 1
@ -1012,12 +1127,16 @@ struct pqi_ctrl_info {
struct mutex scan_mutex;
struct mutex lun_reset_mutex;
struct mutex ofa_mutex; /* serialize ofa */
bool controller_online;
bool block_requests;
bool in_shutdown;
bool in_ofa;
u8 inbound_spanning_supported : 1;
u8 outbound_spanning_supported : 1;
u8 pqi_mode_enabled : 1;
u8 pqi_reset_quiesce_supported : 1;
u8 soft_reset_handshake_supported : 1;
struct list_head scsi_device_list;
spinlock_t scsi_device_list_lock;
@ -1038,6 +1157,7 @@ struct pqi_ctrl_info {
int previous_num_interrupts;
u32 previous_heartbeat_count;
__le32 __iomem *heartbeat_counter;
u8 __iomem *soft_reset_status;
struct timer_list heartbeat_timer;
struct work_struct ctrl_offline_work;
@ -1049,6 +1169,10 @@ struct pqi_ctrl_info {
struct list_head raid_bypass_retry_list;
spinlock_t raid_bypass_retry_list_lock;
struct work_struct raid_bypass_retry_work;
struct pqi_ofa_memory *pqi_ofa_mem_virt_addr;
dma_addr_t pqi_ofa_mem_dma_handle;
void **pqi_ofa_chunk_virt_addr;
};
enum pqi_ctrl_mode {
@ -1078,8 +1202,13 @@ enum pqi_ctrl_mode {
#define BMIC_WRITE 0x27
#define BMIC_SENSE_CONTROLLER_PARAMETERS 0x64
#define BMIC_SENSE_SUBSYSTEM_INFORMATION 0x66
#define BMIC_CSMI_PASSTHRU 0x68
#define BMIC_WRITE_HOST_WELLNESS 0xa5
#define BMIC_FLUSH_CACHE 0xc2
#define BMIC_SET_DIAG_OPTIONS 0xf4
#define BMIC_SENSE_DIAG_OPTIONS 0xf5
#define CSMI_CC_SAS_SMP_PASSTHRU 0X17
#define SA_FLUSH_CACHE 0x1
@ -1107,6 +1236,10 @@ struct bmic_identify_controller {
u8 reserved3[32];
};
#define SA_EXPANDER_SMP_DEVICE 0x05
/*SCSI Invalid Device Type for SAS devices*/
#define PQI_SAS_SCSI_INVALID_DEVTYPE 0xff
struct bmic_identify_physical_device {
u8 scsi_bus; /* SCSI Bus number on controller */
u8 scsi_id; /* SCSI ID on this bus */
@ -1187,6 +1320,50 @@ struct bmic_identify_physical_device {
u8 padding_to_multiple_of_512[9];
};
struct bmic_smp_request {
u8 frame_type;
u8 function;
u8 allocated_response_length;
u8 request_length;
u8 additional_request_bytes[1016];
};
struct bmic_smp_response {
u8 frame_type;
u8 function;
u8 function_result;
u8 response_length;
u8 additional_response_bytes[1016];
};
struct bmic_csmi_ioctl_header {
__le32 header_length;
u8 signature[8];
__le32 timeout;
__le32 control_code;
__le32 return_code;
__le32 length;
};
struct bmic_csmi_smp_passthru {
u8 phy_identifier;
u8 port_identifier;
u8 connection_rate;
u8 reserved;
__be64 destination_sas_address;
__le32 request_length;
struct bmic_smp_request request;
u8 connection_status;
u8 reserved1[3];
__le32 response_length;
struct bmic_smp_response response;
};
struct bmic_csmi_smp_passthru_buffer {
struct bmic_csmi_ioctl_header ioctl_header;
struct bmic_csmi_smp_passthru parameters;
};
struct bmic_flush_cache {
u8 disable_flag;
u8 system_power_action;
@ -1204,8 +1381,42 @@ enum bmic_flush_cache_shutdown_event {
RESTART = 4
};
struct bmic_diag_options {
__le32 options;
};
#pragma pack()
static inline struct pqi_ctrl_info *shost_to_hba(struct Scsi_Host *shost)
{
void *hostdata = shost_priv(shost);
return *((struct pqi_ctrl_info **)hostdata);
}
static inline bool pqi_ctrl_offline(struct pqi_ctrl_info *ctrl_info)
{
return !ctrl_info->controller_online;
}
static inline void pqi_ctrl_busy(struct pqi_ctrl_info *ctrl_info)
{
atomic_inc(&ctrl_info->num_busy_threads);
}
static inline void pqi_ctrl_unbusy(struct pqi_ctrl_info *ctrl_info)
{
atomic_dec(&ctrl_info->num_busy_threads);
}
static inline bool pqi_ctrl_blocked(struct pqi_ctrl_info *ctrl_info)
{
return ctrl_info->block_requests;
}
void pqi_sas_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
struct sas_rphy *rphy);
int pqi_add_sas_host(struct Scsi_Host *shost, struct pqi_ctrl_info *ctrl_info);
void pqi_delete_sas_host(struct pqi_ctrl_info *ctrl_info);
int pqi_add_sas_device(struct pqi_sas_node *pqi_sas_node,
@ -1214,6 +1425,9 @@ void pqi_remove_sas_device(struct pqi_scsi_dev *device);
struct pqi_scsi_dev *pqi_find_device_by_sas_rphy(
struct pqi_ctrl_info *ctrl_info, struct sas_rphy *rphy);
void pqi_prep_for_scsi_done(struct scsi_cmnd *scmd);
int pqi_csmi_smp_passthru(struct pqi_ctrl_info *ctrl_info,
struct bmic_csmi_smp_passthru_buffer *buffer, size_t buffer_length,
struct pqi_raid_error_info *error_info);
extern struct sas_function_template pqi_sas_transport_functions;

File diff suppressed because it is too large Load Diff

View File

@ -17,9 +17,11 @@
*/
#include <linux/kernel.h>
#include <linux/bsg-lib.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_transport_sas.h>
#include <asm/unaligned.h>
#include "smartpqi.h"
static struct pqi_sas_phy *pqi_alloc_sas_phy(struct pqi_sas_port *pqi_sas_port)
@ -97,14 +99,32 @@ static int pqi_sas_port_add_rphy(struct pqi_sas_port *pqi_sas_port,
identify = &rphy->identify;
identify->sas_address = pqi_sas_port->sas_address;
identify->initiator_port_protocols = SAS_PROTOCOL_STP;
identify->target_port_protocols = SAS_PROTOCOL_STP;
if (pqi_sas_port->device &&
pqi_sas_port->device->is_expander_smp_device) {
identify->initiator_port_protocols = SAS_PROTOCOL_SMP;
identify->target_port_protocols = SAS_PROTOCOL_SMP;
} else {
identify->initiator_port_protocols = SAS_PROTOCOL_STP;
identify->target_port_protocols = SAS_PROTOCOL_STP;
}
return sas_rphy_add(rphy);
}
static struct sas_rphy *pqi_sas_rphy_alloc(struct pqi_sas_port *pqi_sas_port)
{
if (pqi_sas_port->device &&
pqi_sas_port->device->is_expander_smp_device)
return sas_expander_alloc(pqi_sas_port->port,
SAS_FANOUT_EXPANDER_DEVICE);
return sas_end_device_alloc(pqi_sas_port->port);
}
static struct pqi_sas_port *pqi_alloc_sas_port(
struct pqi_sas_node *pqi_sas_node, u64 sas_address)
struct pqi_sas_node *pqi_sas_node, u64 sas_address,
struct pqi_scsi_dev *device)
{
int rc;
struct pqi_sas_port *pqi_sas_port;
@ -127,6 +147,7 @@ static struct pqi_sas_port *pqi_alloc_sas_port(
pqi_sas_port->port = port;
pqi_sas_port->sas_address = sas_address;
pqi_sas_port->device = device;
list_add_tail(&pqi_sas_port->port_list_entry,
&pqi_sas_node->port_list_head);
@ -146,7 +167,7 @@ static void pqi_free_sas_port(struct pqi_sas_port *pqi_sas_port)
struct pqi_sas_phy *next;
list_for_each_entry_safe(pqi_sas_phy, next,
&pqi_sas_port->phy_list_head, phy_list_entry)
&pqi_sas_port->phy_list_head, phy_list_entry)
pqi_free_sas_phy(pqi_sas_phy);
sas_port_delete(pqi_sas_port->port);
@ -176,7 +197,7 @@ static void pqi_free_sas_node(struct pqi_sas_node *pqi_sas_node)
return;
list_for_each_entry_safe(pqi_sas_port, next,
&pqi_sas_node->port_list_head, port_list_entry)
&pqi_sas_node->port_list_head, port_list_entry)
pqi_free_sas_port(pqi_sas_port);
kfree(pqi_sas_node);
@ -206,13 +227,14 @@ int pqi_add_sas_host(struct Scsi_Host *shost, struct pqi_ctrl_info *ctrl_info)
struct pqi_sas_port *pqi_sas_port;
struct pqi_sas_phy *pqi_sas_phy;
parent_dev = &shost->shost_gendev;
parent_dev = &shost->shost_dev;
pqi_sas_node = pqi_alloc_sas_node(parent_dev);
if (!pqi_sas_node)
return -ENOMEM;
pqi_sas_port = pqi_alloc_sas_port(pqi_sas_node, ctrl_info->sas_address);
pqi_sas_port = pqi_alloc_sas_port(pqi_sas_node,
ctrl_info->sas_address, NULL);
if (!pqi_sas_port) {
rc = -ENODEV;
goto free_sas_node;
@ -254,11 +276,12 @@ int pqi_add_sas_device(struct pqi_sas_node *pqi_sas_node,
struct pqi_sas_port *pqi_sas_port;
struct sas_rphy *rphy;
pqi_sas_port = pqi_alloc_sas_port(pqi_sas_node, device->sas_address);
pqi_sas_port = pqi_alloc_sas_port(pqi_sas_node,
device->sas_address, device);
if (!pqi_sas_port)
return -ENOMEM;
rphy = sas_end_device_alloc(pqi_sas_port->port);
rphy = pqi_sas_rphy_alloc(pqi_sas_port);
if (!rphy) {
rc = -ENODEV;
goto free_sas_port;
@ -329,6 +352,128 @@ static int pqi_sas_phy_speed(struct sas_phy *phy,
return -EINVAL;
}
#define CSMI_IOCTL_TIMEOUT 60
#define SMP_CRC_FIELD_LENGTH 4
static struct bmic_csmi_smp_passthru_buffer *
pqi_build_csmi_smp_passthru_buffer(struct sas_rphy *rphy,
struct bsg_job *job)
{
struct bmic_csmi_smp_passthru_buffer *smp_buf;
struct bmic_csmi_ioctl_header *ioctl_header;
struct bmic_csmi_smp_passthru *parameters;
u32 req_size;
u32 resp_size;
smp_buf = kzalloc(sizeof(*smp_buf), GFP_KERNEL);
if (!smp_buf)
return NULL;
req_size = job->request_payload.payload_len;
resp_size = job->reply_payload.payload_len;
ioctl_header = &smp_buf->ioctl_header;
put_unaligned_le32(sizeof(smp_buf->ioctl_header),
&ioctl_header->header_length);
put_unaligned_le32(CSMI_IOCTL_TIMEOUT, &ioctl_header->timeout);
put_unaligned_le32(CSMI_CC_SAS_SMP_PASSTHRU,
&ioctl_header->control_code);
put_unaligned_le32(sizeof(smp_buf->parameters), &ioctl_header->length);
parameters = &smp_buf->parameters;
parameters->phy_identifier = rphy->identify.phy_identifier;
parameters->port_identifier = 0;
parameters->connection_rate = 0;
put_unaligned_be64(rphy->identify.sas_address,
&parameters->destination_sas_address);
if (req_size > SMP_CRC_FIELD_LENGTH)
req_size -= SMP_CRC_FIELD_LENGTH;
put_unaligned_le32(req_size, &parameters->request_length);
put_unaligned_le32(resp_size, &parameters->response_length);
sg_copy_to_buffer(job->request_payload.sg_list,
job->reply_payload.sg_cnt, &parameters->request,
req_size);
return smp_buf;
}
static unsigned int pqi_build_sas_smp_handler_reply(
struct bmic_csmi_smp_passthru_buffer *smp_buf, struct bsg_job *job,
struct pqi_raid_error_info *error_info)
{
sg_copy_from_buffer(job->reply_payload.sg_list,
job->reply_payload.sg_cnt, &smp_buf->parameters.response,
le32_to_cpu(smp_buf->parameters.response_length));
job->reply_len = le16_to_cpu(error_info->sense_data_length);
memcpy(job->reply, error_info->data,
le16_to_cpu(error_info->sense_data_length));
return job->reply_payload.payload_len -
get_unaligned_le32(&error_info->data_in_transferred);
}
void pqi_sas_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
struct sas_rphy *rphy)
{
int rc;
struct pqi_ctrl_info *ctrl_info = shost_to_hba(shost);
struct bmic_csmi_smp_passthru_buffer *smp_buf;
struct pqi_raid_error_info error_info;
unsigned int reslen = 0;
pqi_ctrl_busy(ctrl_info);
if (job->reply_payload.payload_len == 0) {
rc = -ENOMEM;
goto out;
}
if (!rphy) {
rc = -EINVAL;
goto out;
}
if (rphy->identify.device_type != SAS_FANOUT_EXPANDER_DEVICE) {
rc = -EINVAL;
goto out;
}
if (job->request_payload.sg_cnt > 1 || job->reply_payload.sg_cnt > 1) {
rc = -EINVAL;
goto out;
}
if (pqi_ctrl_offline(ctrl_info)) {
rc = -ENXIO;
goto out;
}
if (pqi_ctrl_blocked(ctrl_info)) {
rc = -EBUSY;
goto out;
}
smp_buf = pqi_build_csmi_smp_passthru_buffer(rphy, job);
if (!smp_buf) {
rc = -ENOMEM;
goto out;
}
rc = pqi_csmi_smp_passthru(ctrl_info, smp_buf, sizeof(*smp_buf),
&error_info);
if (rc)
goto out;
reslen = pqi_build_sas_smp_handler_reply(smp_buf, job, &error_info);
out:
bsg_job_done(job, rc, reslen);
pqi_ctrl_unbusy(ctrl_info);
}
struct sas_function_template pqi_sas_transport_functions = {
.get_linkerrors = pqi_sas_get_linkerrors,
.get_enclosure_identifier = pqi_sas_get_enclosure_identifier,
@ -338,4 +483,5 @@ struct sas_function_template pqi_sas_transport_functions = {
.phy_setup = pqi_sas_phy_setup,
.phy_release = pqi_sas_phy_release,
.set_phy_speed = pqi_sas_phy_speed,
.smp_handler = pqi_sas_smp_handler,
};

View File

@ -34,6 +34,7 @@
#define SIS_REENABLE_SIS_MODE 0x1
#define SIS_ENABLE_MSIX 0x40
#define SIS_ENABLE_INTX 0x80
#define SIS_SOFT_RESET 0x100
#define SIS_CMD_READY 0x200
#define SIS_TRIGGER_SHUTDOWN 0x800000
#define SIS_PQI_RESET_QUIESCE 0x1000000
@ -90,7 +91,7 @@ static int sis_wait_for_ctrl_ready_with_timeout(struct pqi_ctrl_info *ctrl_info,
unsigned long timeout;
u32 status;
timeout = (timeout_secs * HZ) + jiffies;
timeout = (timeout_secs * PQI_HZ) + jiffies;
while (1) {
status = readl(&ctrl_info->registers->sis_firmware_status);
@ -202,7 +203,7 @@ static int sis_send_sync_cmd(struct pqi_ctrl_info *ctrl_info,
* the top of the loop in order to give the controller time to start
* processing the command before we start polling.
*/
timeout = (SIS_CMD_COMPLETE_TIMEOUT_SECS * HZ) + jiffies;
timeout = (SIS_CMD_COMPLETE_TIMEOUT_SECS * PQI_HZ) + jiffies;
while (1) {
msleep(SIS_CMD_COMPLETE_POLL_INTERVAL_MSECS);
doorbell = readl(&registers->sis_ctrl_to_host_doorbell);
@ -316,9 +317,9 @@ int sis_init_base_struct_addr(struct pqi_ctrl_info *ctrl_info)
put_unaligned_le32(ctrl_info->max_io_slots,
&base_struct->error_buffer_num_elements);
bus_address = pci_map_single(ctrl_info->pci_dev, base_struct,
sizeof(*base_struct), PCI_DMA_TODEVICE);
if (pci_dma_mapping_error(ctrl_info->pci_dev, bus_address)) {
bus_address = dma_map_single(&ctrl_info->pci_dev->dev, base_struct,
sizeof(*base_struct), DMA_TO_DEVICE);
if (dma_mapping_error(&ctrl_info->pci_dev->dev, bus_address)) {
rc = -ENOMEM;
goto out;
}
@ -331,9 +332,8 @@ int sis_init_base_struct_addr(struct pqi_ctrl_info *ctrl_info)
rc = sis_send_sync_cmd(ctrl_info, SIS_CMD_INIT_BASE_STRUCT_ADDRESS,
&params);
pci_unmap_single(ctrl_info->pci_dev, bus_address, sizeof(*base_struct),
PCI_DMA_TODEVICE);
dma_unmap_single(&ctrl_info->pci_dev->dev, bus_address,
sizeof(*base_struct), DMA_TO_DEVICE);
out:
kfree(base_struct_unaligned);
@ -349,7 +349,7 @@ static int sis_wait_for_doorbell_bit_to_clear(
u32 doorbell_register;
unsigned long timeout;
timeout = (SIS_DOORBELL_BIT_CLEAR_TIMEOUT_SECS * HZ) + jiffies;
timeout = (SIS_DOORBELL_BIT_CLEAR_TIMEOUT_SECS * PQI_HZ) + jiffies;
while (1) {
doorbell_register =
@ -421,6 +421,12 @@ u32 sis_read_driver_scratch(struct pqi_ctrl_info *ctrl_info)
return readl(&ctrl_info->registers->sis_driver_scratch);
}
void sis_soft_reset(struct pqi_ctrl_info *ctrl_info)
{
writel(SIS_SOFT_RESET,
&ctrl_info->registers->sis_host_to_ctrl_doorbell);
}
static void __attribute__((unused)) verify_structures(void)
{
BUILD_BUG_ON(offsetof(struct sis_base_struct,

View File

@ -33,5 +33,6 @@ int sis_pqi_reset_quiesce(struct pqi_ctrl_info *ctrl_info);
int sis_reenable_sis_mode(struct pqi_ctrl_info *ctrl_info);
void sis_write_driver_scratch(struct pqi_ctrl_info *ctrl_info, u32 value);
u32 sis_read_driver_scratch(struct pqi_ctrl_info *ctrl_info);
void sis_soft_reset(struct pqi_ctrl_info *ctrl_info);
#endif /* _SMARTPQI_SIS_H */

View File

@ -373,7 +373,7 @@ static inline unsigned int xt_write_recseq_begin(void)
* since addend is most likely 1
*/
__this_cpu_add(xt_recseq.sequence, addend);
smp_wmb();
smp_mb();
return addend;
}

View File

@ -5449,28 +5449,43 @@ static int wake_wide(struct task_struct *p)
* soonest. For the purpose of speed we only consider the waking and previous
* CPU.
*
* wake_affine_idle() - only considers 'now', it check if the waking CPU is (or
* will be) idle.
* wake_affine_idle() - only considers 'now', it check if the waking CPU is
* cache-affine and is (or will be) idle.
*
* wake_affine_weight() - considers the weight to reflect the average
* scheduling latency of the CPUs. This seems to work
* for the overloaded case.
*/
static bool
static int
wake_affine_idle(struct sched_domain *sd, struct task_struct *p,
int this_cpu, int prev_cpu, int sync)
{
if (idle_cpu(this_cpu))
return true;
/*
* If this_cpu is idle, it implies the wakeup is from interrupt
* context. Only allow the move if cache is shared. Otherwise an
* interrupt intensive workload could force all tasks onto one
* node depending on the IO topology or IRQ affinity settings.
*
* If the prev_cpu is idle and cache affine then avoid a migration.
* There is no guarantee that the cache hot data from an interrupt
* is more important than cache hot data on the prev_cpu and from
* a cpufreq perspective, it's better to have higher utilisation
* on one CPU.
*/
if (idle_cpu(this_cpu) && cpus_share_cache(this_cpu, prev_cpu))
return idle_cpu(prev_cpu) ? prev_cpu : this_cpu;
if (sync && cpu_rq(this_cpu)->nr_running == 1)
return true;
return this_cpu;
return false;
if (idle_cpu(prev_cpu))
return prev_cpu;
return nr_cpumask_bits;
}
static bool
static int
wake_affine_weight(struct sched_domain *sd, struct task_struct *p,
int this_cpu, int prev_cpu, int sync)
{
@ -5484,7 +5499,7 @@ wake_affine_weight(struct sched_domain *sd, struct task_struct *p,
unsigned long current_load = task_h_load(current);
if (current_load > this_eff_load)
return true;
return this_cpu;
this_eff_load -= current_load;
}
@ -5501,7 +5516,16 @@ wake_affine_weight(struct sched_domain *sd, struct task_struct *p,
prev_eff_load *= 100 + (sd->imbalance_pct - 100) / 2;
prev_eff_load *= capacity_of(this_cpu);
return this_eff_load <= prev_eff_load;
/*
* If sync, adjust the weight of prev_eff_load such that if
* prev_eff == this_eff that select_idle_sibling() will consider
* stacking the wakee on top of the waker if no other CPU is
* idle.
*/
if (sync)
prev_eff_load += 1;
return this_eff_load < prev_eff_load ? this_cpu : nr_cpumask_bits;
}
static int wake_affine(struct sched_domain *sd, struct task_struct *p,
@ -5509,14 +5533,17 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p,
{
int this_cpu = smp_processor_id();
bool affine = false;
int target = nr_cpumask_bits;
if (sched_feat(WA_IDLE) && !affine)
affine = wake_affine_idle(sd, p, this_cpu, prev_cpu, sync);
if (sched_feat(WA_IDLE))
target = wake_affine_idle(sd, p, this_cpu, prev_cpu, sync);
if (sched_feat(WA_WEIGHT) && !affine)
affine = wake_affine_weight(sd, p, this_cpu, prev_cpu, sync);
if (sched_feat(WA_WEIGHT) && target == nr_cpumask_bits)
target = wake_affine_weight(sd, p, this_cpu, prev_cpu, sync);
schedstat_inc(p->se.statistics.nr_wakeups_affine_attempts);
if (target == this_cpu)
affine = true;
if (affine) {
schedstat_inc(sd->ttwu_move_affine);
schedstat_inc(p->se.statistics.nr_wakeups_affine);

View File

@ -638,6 +638,25 @@ static void get_counters(const struct xt_table_info *t,
}
}
static void get_old_counters(const struct xt_table_info *t,
struct xt_counters counters[])
{
struct arpt_entry *iter;
unsigned int cpu, i;
for_each_possible_cpu(cpu) {
i = 0;
xt_entry_foreach(iter, t->entries, t->size) {
struct xt_counters *tmp;
tmp = xt_get_per_cpu_counter(&iter->counters, cpu);
ADD_COUNTER(counters[i], tmp->bcnt, tmp->pcnt);
++i;
}
cond_resched();
}
}
static struct xt_counters *alloc_counters(const struct xt_table *table)
{
unsigned int countersize;
@ -916,8 +935,7 @@ static int __do_replace(struct net *net, const char *name,
(newinfo->number <= oldinfo->initial_entries))
module_put(t->me);
/* Get the old counters, and synchronize with replace */
get_counters(oldinfo, counters);
get_old_counters(oldinfo, counters);
/* Decrease module usage counts and free resource */
loc_cpu_old_entry = oldinfo->entries;

View File

@ -787,6 +787,27 @@ get_counters(const struct xt_table_info *t,
}
}
static void get_old_counters(const struct xt_table_info *t,
struct xt_counters counters[])
{
struct ipt_entry *iter;
unsigned int cpu, i;
for_each_possible_cpu(cpu) {
i = 0;
xt_entry_foreach(iter, t->entries, t->size) {
const struct xt_counters *tmp;
tmp = xt_get_per_cpu_counter(&iter->counters, cpu);
ADD_COUNTER(counters[i], tmp->bcnt, tmp->pcnt);
++i; /* macro does multi eval of i */
}
cond_resched();
}
}
static struct xt_counters *alloc_counters(const struct xt_table *table)
{
unsigned int countersize;
@ -1078,8 +1099,7 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
(newinfo->number <= oldinfo->initial_entries))
module_put(t->me);
/* Get the old counters, and synchronize with replace */
get_counters(oldinfo, counters);
get_old_counters(oldinfo, counters);
/* Decrease module usage counts and free resource */
xt_entry_foreach(iter, oldinfo->entries, oldinfo->size)

View File

@ -1403,6 +1403,7 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe,
return ret;
}
static void rt_add_uncached_list(struct rtable *rt);
static bool rt_cache_route(struct fib_nh *nh, struct rtable *rt)
{
struct rtable *orig, *prev, **p;
@ -1422,7 +1423,7 @@ static bool rt_cache_route(struct fib_nh *nh, struct rtable *rt)
prev = cmpxchg(p, orig, rt);
if (prev == orig) {
if (orig) {
dst_dev_put(&orig->dst);
rt_add_uncached_list(orig);
dst_release(&orig->dst);
}
} else {

View File

@ -805,6 +805,25 @@ get_counters(const struct xt_table_info *t,
}
}
static void get_old_counters(const struct xt_table_info *t,
struct xt_counters counters[])
{
struct ip6t_entry *iter;
unsigned int cpu, i;
for_each_possible_cpu(cpu) {
i = 0;
xt_entry_foreach(iter, t->entries, t->size) {
const struct xt_counters *tmp;
tmp = xt_get_per_cpu_counter(&iter->counters, cpu);
ADD_COUNTER(counters[i], tmp->bcnt, tmp->pcnt);
++i;
}
cond_resched();
}
}
static struct xt_counters *alloc_counters(const struct xt_table *table)
{
unsigned int countersize;
@ -1097,8 +1116,7 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
(newinfo->number <= oldinfo->initial_entries))
module_put(t->me);
/* Get the old counters, and synchronize with replace */
get_counters(oldinfo, counters);
get_old_counters(oldinfo, counters);
/* Decrease module usage counts and free resource */
xt_entry_foreach(iter, oldinfo->entries, oldinfo->size)

View File

@ -1225,6 +1225,7 @@ xt_replace_table(struct xt_table *table,
{
struct xt_table_info *private;
int ret;
unsigned int cpu;
ret = xt_jumpstack_alloc(newinfo);
if (ret < 0) {
@ -1253,14 +1254,26 @@ xt_replace_table(struct xt_table *table,
smp_wmb();
table->private = newinfo;
/* make sure all cpus see new ->private value */
smp_mb();
/*
* Even though table entries have now been swapped, other CPU's
* may still be using the old entries. This is okay, because
* resynchronization happens because of the locking done
* during the get_counters() routine.
* may still be using the old entries...
*/
local_bh_enable();
/* ... so wait for even xt_recseq on all cpus */
for_each_possible_cpu(cpu) {
seqcount_t *s = &per_cpu(xt_recseq, cpu);
u32 seq = raw_read_seqcount(s);
if (seq & 1) {
do {
cond_resched();
cpu_relax();
} while (seq == raw_read_seqcount(s));
}
}
#ifdef CONFIG_AUDIT
if (audit_enabled) {
audit_log(current->audit_context, GFP_KERNEL,

View File

@ -644,10 +644,10 @@ CONFIG_EFI_STUB=y
# CONFIG_EFI_MIXED is not set
CONFIG_SECCOMP=y
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
# CONFIG_HZ_250 is not set
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_HZ_1000=y
CONFIG_HZ=1000
CONFIG_SCHED_HRTICK=y
CONFIG_KEXEC=y
# CONFIG_KEXEC_FILE is not set
@ -1715,7 +1715,7 @@ CONFIG_SCSI_ARCMSR=y
CONFIG_SCSI_MPT3SAS=y
CONFIG_SCSI_MPT2SAS_MAX_SGE=128
CONFIG_SCSI_MPT3SAS_MAX_SGE=128
# CONFIG_SCSI_SMARTPQI is not set
CONFIG_SCSI_SMARTPQI=y
CONFIG_SCSI_UFSHCD=y
CONFIG_SCSI_UFSHCD_PCI=y
# CONFIG_SCSI_UFS_DWC_TC_PCI is not set