diff options
40 files changed, 1210 insertions, 633 deletions
diff --git a/Documentation/isdn/00-INDEX b/Documentation/isdn/00-INDEX index f6010a536590..e87e336f590e 100644 --- a/Documentation/isdn/00-INDEX +++ b/Documentation/isdn/00-INDEX | |||
| @@ -14,25 +14,14 @@ README | |||
| 14 | - general info on what you need and what to do for Linux ISDN. | 14 | - general info on what you need and what to do for Linux ISDN. |
| 15 | README.FAQ | 15 | README.FAQ |
| 16 | - general info for FAQ. | 16 | - general info for FAQ. |
| 17 | README.audio | ||
| 18 | - info for running audio over ISDN. | ||
| 19 | README.fax | ||
| 20 | - info for using Fax over ISDN. | ||
| 21 | README.gigaset | ||
| 22 | - info on the drivers for Siemens Gigaset ISDN adapters. | ||
| 23 | README.icn | ||
| 24 | - info on the ICN-ISDN-card and its driver. | ||
| 25 | >>>>>>> 93af7aca44f0e82e67bda10a0fb73d383edcc8bd:Documentation/isdn/00-INDEX | ||
| 26 | README.HiSax | 17 | README.HiSax |
| 27 | - info on the HiSax driver which replaces the old teles. | 18 | - info on the HiSax driver which replaces the old teles. |
| 19 | README.act2000 | ||
| 20 | - info on driver for IBM ACT-2000 card. | ||
| 28 | README.audio | 21 | README.audio |
| 29 | - info for running audio over ISDN. | 22 | - info for running audio over ISDN. |
| 30 | README.avmb1 | 23 | README.avmb1 |
| 31 | - info on driver for AVM-B1 ISDN card. | 24 | - info on driver for AVM-B1 ISDN card. |
| 32 | README.act2000 | ||
| 33 | - info on driver for IBM ACT-2000 card. | ||
| 34 | README.eicon | ||
| 35 | - info on driver for Eicon active cards. | ||
| 36 | README.concap | 25 | README.concap |
| 37 | - info on "CONCAP" encapsulation protocol interface used for X.25. | 26 | - info on "CONCAP" encapsulation protocol interface used for X.25. |
| 38 | README.diversion | 27 | README.diversion |
| @@ -59,7 +48,3 @@ README.x25 | |||
| 59 | - info for running X.25 over ISDN. | 48 | - info for running X.25 over ISDN. |
| 60 | syncPPP.FAQ | 49 | syncPPP.FAQ |
| 61 | - frequently asked questions about running PPP over ISDN. | 50 | - frequently asked questions about running PPP over ISDN. |
| 62 | README.hysdn | ||
| 63 | - info on driver for Hypercope active HYSDN cards | ||
| 64 | README.mISDN | ||
| 65 | - info on the Modular ISDN subsystem (mISDN). | ||
diff --git a/Documentation/rfkill.txt b/Documentation/rfkill.txt index c8acd8659e91..b4860509c319 100644 --- a/Documentation/rfkill.txt +++ b/Documentation/rfkill.txt | |||
| @@ -111,6 +111,8 @@ following attributes: | |||
| 111 | 111 | ||
| 112 | name: Name assigned by driver to this key (interface or driver name). | 112 | name: Name assigned by driver to this key (interface or driver name). |
| 113 | type: Driver type string ("wlan", "bluetooth", etc). | 113 | type: Driver type string ("wlan", "bluetooth", etc). |
| 114 | persistent: Whether the soft blocked state is initialised from | ||
| 115 | non-volatile storage at startup. | ||
| 114 | state: Current state of the transmitter | 116 | state: Current state of the transmitter |
| 115 | 0: RFKILL_STATE_SOFT_BLOCKED | 117 | 0: RFKILL_STATE_SOFT_BLOCKED |
| 116 | transmitter is turned off by software | 118 | transmitter is turned off by software |
diff --git a/MAINTAINERS b/MAINTAINERS index 1d4704300c1d..b114632050bf 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -2853,7 +2853,7 @@ P: Sergey Lapin | |||
| 2853 | M: slapin@ossfans.org | 2853 | M: slapin@ossfans.org |
| 2854 | L: linux-zigbee-devel@lists.sourceforge.net | 2854 | L: linux-zigbee-devel@lists.sourceforge.net |
| 2855 | W: http://apps.sourceforge.net/trac/linux-zigbee | 2855 | W: http://apps.sourceforge.net/trac/linux-zigbee |
| 2856 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/lumag/lowpan.git | 2856 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/lowpan/lowpan.git |
| 2857 | S: Maintained | 2857 | S: Maintained |
| 2858 | F: net/ieee802154/ | 2858 | F: net/ieee802154/ |
| 2859 | F: drivers/ieee802154/ | 2859 | F: drivers/ieee802154/ |
diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index b4bb06fdf307..f703758f0a6e 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h | |||
| @@ -65,7 +65,7 @@ static inline char *nic_name(struct pci_dev *pdev) | |||
| 65 | #define TX_CQ_LEN 1024 | 65 | #define TX_CQ_LEN 1024 |
| 66 | #define RX_Q_LEN 1024 /* Does not support any other value */ | 66 | #define RX_Q_LEN 1024 /* Does not support any other value */ |
| 67 | #define RX_CQ_LEN 1024 | 67 | #define RX_CQ_LEN 1024 |
| 68 | #define MCC_Q_LEN 64 /* total size not to exceed 8 pages */ | 68 | #define MCC_Q_LEN 128 /* total size not to exceed 8 pages */ |
| 69 | #define MCC_CQ_LEN 256 | 69 | #define MCC_CQ_LEN 256 |
| 70 | 70 | ||
| 71 | #define BE_NAPI_WEIGHT 64 | 71 | #define BE_NAPI_WEIGHT 64 |
| @@ -91,6 +91,61 @@ struct be_queue_info { | |||
| 91 | atomic_t used; /* Number of valid elements in the queue */ | 91 | atomic_t used; /* Number of valid elements in the queue */ |
| 92 | }; | 92 | }; |
| 93 | 93 | ||
| 94 | static inline u32 MODULO(u16 val, u16 limit) | ||
| 95 | { | ||
| 96 | BUG_ON(limit & (limit - 1)); | ||
| 97 | return val & (limit - 1); | ||
| 98 | } | ||
| 99 | |||
| 100 | static inline void index_adv(u16 *index, u16 val, u16 limit) | ||
| 101 | { | ||
| 102 | *index = MODULO((*index + val), limit); | ||
| 103 | } | ||
| 104 | |||
| 105 | static inline void index_inc(u16 *index, u16 limit) | ||
| 106 | { | ||
| 107 | *index = MODULO((*index + 1), limit); | ||
| 108 | } | ||
| 109 | |||
| 110 | static inline void *queue_head_node(struct be_queue_info *q) | ||
| 111 | { | ||
| 112 | return q->dma_mem.va + q->head * q->entry_size; | ||
| 113 | } | ||
| 114 | |||
| 115 | static inline void *queue_tail_node(struct be_queue_info *q) | ||
| 116 | { | ||
| 117 | return q->dma_mem.va + q->tail * q->entry_size; | ||
| 118 | } | ||
| 119 | |||
| 120 | static inline void queue_head_inc(struct be_queue_info *q) | ||
| 121 | { | ||
| 122 | index_inc(&q->head, q->len); | ||
| 123 | } | ||
| 124 | |||
| 125 | static inline void queue_tail_inc(struct be_queue_info *q) | ||
| 126 | { | ||
| 127 | index_inc(&q->tail, q->len); | ||
| 128 | } | ||
| 129 | |||
| 130 | |||
| 131 | struct be_eq_obj { | ||
| 132 | struct be_queue_info q; | ||
| 133 | char desc[32]; | ||
| 134 | |||
| 135 | /* Adaptive interrupt coalescing (AIC) info */ | ||
| 136 | bool enable_aic; | ||
| 137 | u16 min_eqd; /* in usecs */ | ||
| 138 | u16 max_eqd; /* in usecs */ | ||
| 139 | u16 cur_eqd; /* in usecs */ | ||
| 140 | |||
| 141 | struct napi_struct napi; | ||
| 142 | }; | ||
| 143 | |||
| 144 | struct be_mcc_obj { | ||
| 145 | struct be_queue_info q; | ||
| 146 | struct be_queue_info cq; | ||
| 147 | }; | ||
| 148 | |||
| 94 | struct be_ctrl_info { | 149 | struct be_ctrl_info { |
| 95 | u8 __iomem *csr; | 150 | u8 __iomem *csr; |
| 96 | u8 __iomem *db; /* Door Bell */ | 151 | u8 __iomem *db; /* Door Bell */ |
| @@ -98,11 +153,20 @@ struct be_ctrl_info { | |||
| 98 | int pci_func; | 153 | int pci_func; |
| 99 | 154 | ||
| 100 | /* Mbox used for cmd request/response */ | 155 | /* Mbox used for cmd request/response */ |
| 101 | spinlock_t cmd_lock; /* For serializing cmds to BE card */ | 156 | spinlock_t mbox_lock; /* For serializing mbox cmds to BE card */ |
| 102 | struct be_dma_mem mbox_mem; | 157 | struct be_dma_mem mbox_mem; |
| 103 | /* Mbox mem is adjusted to align to 16 bytes. The allocated addr | 158 | /* Mbox mem is adjusted to align to 16 bytes. The allocated addr |
| 104 | * is stored for freeing purpose */ | 159 | * is stored for freeing purpose */ |
| 105 | struct be_dma_mem mbox_mem_alloced; | 160 | struct be_dma_mem mbox_mem_alloced; |
| 161 | |||
| 162 | /* MCC Rings */ | ||
| 163 | struct be_mcc_obj mcc_obj; | ||
| 164 | spinlock_t mcc_lock; /* For serializing mcc cmds to BE card */ | ||
| 165 | spinlock_t mcc_cq_lock; | ||
| 166 | |||
| 167 | /* MCC Async callback */ | ||
| 168 | void (*async_cb)(void *adapter, bool link_up); | ||
| 169 | void *adapter_ctxt; | ||
| 106 | }; | 170 | }; |
| 107 | 171 | ||
| 108 | #include "be_cmds.h" | 172 | #include "be_cmds.h" |
| @@ -150,19 +214,6 @@ struct be_stats_obj { | |||
| 150 | struct be_dma_mem cmd; | 214 | struct be_dma_mem cmd; |
| 151 | }; | 215 | }; |
| 152 | 216 | ||
| 153 | struct be_eq_obj { | ||
| 154 | struct be_queue_info q; | ||
| 155 | char desc[32]; | ||
| 156 | |||
| 157 | /* Adaptive interrupt coalescing (AIC) info */ | ||
| 158 | bool enable_aic; | ||
| 159 | u16 min_eqd; /* in usecs */ | ||
| 160 | u16 max_eqd; /* in usecs */ | ||
| 161 | u16 cur_eqd; /* in usecs */ | ||
| 162 | |||
| 163 | struct napi_struct napi; | ||
| 164 | }; | ||
| 165 | |||
| 166 | struct be_tx_obj { | 217 | struct be_tx_obj { |
| 167 | struct be_queue_info q; | 218 | struct be_queue_info q; |
| 168 | struct be_queue_info cq; | 219 | struct be_queue_info cq; |
| @@ -225,8 +276,9 @@ struct be_adapter { | |||
| 225 | u32 if_handle; /* Used to configure filtering */ | 276 | u32 if_handle; /* Used to configure filtering */ |
| 226 | u32 pmac_id; /* MAC addr handle used by BE card */ | 277 | u32 pmac_id; /* MAC addr handle used by BE card */ |
| 227 | 278 | ||
| 228 | struct be_link_info link; | 279 | bool link_up; |
| 229 | u32 port_num; | 280 | u32 port_num; |
| 281 | bool promiscuous; | ||
| 230 | }; | 282 | }; |
| 231 | 283 | ||
| 232 | extern struct ethtool_ops be_ethtool_ops; | 284 | extern struct ethtool_ops be_ethtool_ops; |
| @@ -235,22 +287,6 @@ extern struct ethtool_ops be_ethtool_ops; | |||
| 235 | 287 | ||
| 236 | #define BE_SET_NETDEV_OPS(netdev, ops) (netdev->netdev_ops = ops) | 288 | #define BE_SET_NETDEV_OPS(netdev, ops) (netdev->netdev_ops = ops) |
| 237 | 289 | ||
| 238 | static inline u32 MODULO(u16 val, u16 limit) | ||
| 239 | { | ||
| 240 | BUG_ON(limit & (limit - 1)); | ||
| 241 | return val & (limit - 1); | ||
| 242 | } | ||
| 243 | |||
| 244 | static inline void index_adv(u16 *index, u16 val, u16 limit) | ||
| 245 | { | ||
| 246 | *index = MODULO((*index + val), limit); | ||
| 247 | } | ||
| 248 | |||
| 249 | static inline void index_inc(u16 *index, u16 limit) | ||
| 250 | { | ||
| 251 | *index = MODULO((*index + 1), limit); | ||
| 252 | } | ||
| 253 | |||
| 254 | #define PAGE_SHIFT_4K 12 | 290 | #define PAGE_SHIFT_4K 12 |
| 255 | #define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K) | 291 | #define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K) |
| 256 | 292 | ||
| @@ -339,4 +375,6 @@ static inline u8 is_udp_pkt(struct sk_buff *skb) | |||
| 339 | return val; | 375 | return val; |
| 340 | } | 376 | } |
| 341 | 377 | ||
| 378 | extern void be_cq_notify(struct be_ctrl_info *ctrl, u16 qid, bool arm, | ||
| 379 | u16 num_popped); | ||
| 342 | #endif /* BE_H */ | 380 | #endif /* BE_H */ |
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index d444aed962bc..583517ed56f0 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c | |||
| @@ -17,6 +17,133 @@ | |||
| 17 | 17 | ||
| 18 | #include "be.h" | 18 | #include "be.h" |
| 19 | 19 | ||
| 20 | static void be_mcc_notify(struct be_ctrl_info *ctrl) | ||
| 21 | { | ||
| 22 | struct be_queue_info *mccq = &ctrl->mcc_obj.q; | ||
| 23 | u32 val = 0; | ||
| 24 | |||
| 25 | val |= mccq->id & DB_MCCQ_RING_ID_MASK; | ||
| 26 | val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT; | ||
| 27 | iowrite32(val, ctrl->db + DB_MCCQ_OFFSET); | ||
| 28 | } | ||
| 29 | |||
| 30 | /* To check if valid bit is set, check the entire word as we don't know | ||
| 31 | * the endianness of the data (old entry is host endian while a new entry is | ||
| 32 | * little endian) */ | ||
| 33 | static inline bool be_mcc_compl_is_new(struct be_mcc_cq_entry *compl) | ||
| 34 | { | ||
| 35 | if (compl->flags != 0) { | ||
| 36 | compl->flags = le32_to_cpu(compl->flags); | ||
| 37 | BUG_ON((compl->flags & CQE_FLAGS_VALID_MASK) == 0); | ||
| 38 | return true; | ||
| 39 | } else { | ||
| 40 | return false; | ||
| 41 | } | ||
| 42 | } | ||
| 43 | |||
| 44 | /* Need to reset the entire word that houses the valid bit */ | ||
| 45 | static inline void be_mcc_compl_use(struct be_mcc_cq_entry *compl) | ||
| 46 | { | ||
| 47 | compl->flags = 0; | ||
| 48 | } | ||
| 49 | |||
| 50 | static int be_mcc_compl_process(struct be_ctrl_info *ctrl, | ||
| 51 | struct be_mcc_cq_entry *compl) | ||
| 52 | { | ||
| 53 | u16 compl_status, extd_status; | ||
| 54 | |||
| 55 | /* Just swap the status to host endian; mcc tag is opaquely copied | ||
| 56 | * from mcc_wrb */ | ||
| 57 | be_dws_le_to_cpu(compl, 4); | ||
| 58 | |||
| 59 | compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) & | ||
| 60 | CQE_STATUS_COMPL_MASK; | ||
| 61 | if (compl_status != MCC_STATUS_SUCCESS) { | ||
| 62 | extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) & | ||
| 63 | CQE_STATUS_EXTD_MASK; | ||
| 64 | printk(KERN_WARNING DRV_NAME | ||
| 65 | " error in cmd completion: status(compl/extd)=%d/%d\n", | ||
| 66 | compl_status, extd_status); | ||
| 67 | return -1; | ||
| 68 | } | ||
| 69 | return 0; | ||
| 70 | } | ||
| 71 | |||
| 72 | /* Link state evt is a string of bytes; no need for endian swapping */ | ||
| 73 | static void be_async_link_state_process(struct be_ctrl_info *ctrl, | ||
| 74 | struct be_async_event_link_state *evt) | ||
| 75 | { | ||
| 76 | ctrl->async_cb(ctrl->adapter_ctxt, | ||
| 77 | evt->port_link_status == ASYNC_EVENT_LINK_UP ? true : false); | ||
| 78 | } | ||
| 79 | |||
| 80 | static inline bool is_link_state_evt(u32 trailer) | ||
| 81 | { | ||
| 82 | return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) & | ||
| 83 | ASYNC_TRAILER_EVENT_CODE_MASK) == | ||
| 84 | ASYNC_EVENT_CODE_LINK_STATE); | ||
| 85 | } | ||
| 86 | |||
| 87 | static struct be_mcc_cq_entry *be_mcc_compl_get(struct be_ctrl_info *ctrl) | ||
| 88 | { | ||
| 89 | struct be_queue_info *mcc_cq = &ctrl->mcc_obj.cq; | ||
| 90 | struct be_mcc_cq_entry *compl = queue_tail_node(mcc_cq); | ||
| 91 | |||
| 92 | if (be_mcc_compl_is_new(compl)) { | ||
| 93 | queue_tail_inc(mcc_cq); | ||
| 94 | return compl; | ||
| 95 | } | ||
| 96 | return NULL; | ||
| 97 | } | ||
| 98 | |||
| 99 | void be_process_mcc(struct be_ctrl_info *ctrl) | ||
| 100 | { | ||
| 101 | struct be_mcc_cq_entry *compl; | ||
| 102 | int num = 0; | ||
| 103 | |||
| 104 | spin_lock_bh(&ctrl->mcc_cq_lock); | ||
| 105 | while ((compl = be_mcc_compl_get(ctrl))) { | ||
| 106 | if (compl->flags & CQE_FLAGS_ASYNC_MASK) { | ||
| 107 | /* Interpret flags as an async trailer */ | ||
| 108 | BUG_ON(!is_link_state_evt(compl->flags)); | ||
| 109 | |||
| 110 | /* Interpret compl as a async link evt */ | ||
| 111 | be_async_link_state_process(ctrl, | ||
| 112 | (struct be_async_event_link_state *) compl); | ||
| 113 | } else { | ||
| 114 | be_mcc_compl_process(ctrl, compl); | ||
| 115 | atomic_dec(&ctrl->mcc_obj.q.used); | ||
| 116 | } | ||
| 117 | be_mcc_compl_use(compl); | ||
| 118 | num++; | ||
| 119 | } | ||
| 120 | if (num) | ||
| 121 | be_cq_notify(ctrl, ctrl->mcc_obj.cq.id, true, num); | ||
| 122 | spin_unlock_bh(&ctrl->mcc_cq_lock); | ||
| 123 | } | ||
| 124 | |||
| 125 | /* Wait till no more pending mcc requests are present */ | ||
| 126 | static void be_mcc_wait_compl(struct be_ctrl_info *ctrl) | ||
| 127 | { | ||
| 128 | #define mcc_timeout 50000 /* 5s timeout */ | ||
| 129 | int i; | ||
| 130 | for (i = 0; i < mcc_timeout; i++) { | ||
| 131 | be_process_mcc(ctrl); | ||
| 132 | if (atomic_read(&ctrl->mcc_obj.q.used) == 0) | ||
| 133 | break; | ||
| 134 | udelay(100); | ||
| 135 | } | ||
| 136 | if (i == mcc_timeout) | ||
| 137 | printk(KERN_WARNING DRV_NAME "mcc poll timed out\n"); | ||
| 138 | } | ||
| 139 | |||
| 140 | /* Notify MCC requests and wait for completion */ | ||
| 141 | static void be_mcc_notify_wait(struct be_ctrl_info *ctrl) | ||
| 142 | { | ||
| 143 | be_mcc_notify(ctrl); | ||
| 144 | be_mcc_wait_compl(ctrl); | ||
| 145 | } | ||
| 146 | |||
| 20 | static int be_mbox_db_ready_wait(void __iomem *db) | 147 | static int be_mbox_db_ready_wait(void __iomem *db) |
| 21 | { | 148 | { |
| 22 | int cnt = 0, wait = 5; | 149 | int cnt = 0, wait = 5; |
| @@ -44,11 +171,11 @@ static int be_mbox_db_ready_wait(void __iomem *db) | |||
| 44 | 171 | ||
| 45 | /* | 172 | /* |
| 46 | * Insert the mailbox address into the doorbell in two steps | 173 | * Insert the mailbox address into the doorbell in two steps |
| 174 | * Polls on the mbox doorbell till a command completion (or a timeout) occurs | ||
| 47 | */ | 175 | */ |
| 48 | static int be_mbox_db_ring(struct be_ctrl_info *ctrl) | 176 | static int be_mbox_db_ring(struct be_ctrl_info *ctrl) |
| 49 | { | 177 | { |
| 50 | int status; | 178 | int status; |
| 51 | u16 compl_status, extd_status; | ||
| 52 | u32 val = 0; | 179 | u32 val = 0; |
| 53 | void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; | 180 | void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; |
| 54 | struct be_dma_mem *mbox_mem = &ctrl->mbox_mem; | 181 | struct be_dma_mem *mbox_mem = &ctrl->mbox_mem; |
| @@ -79,24 +206,17 @@ static int be_mbox_db_ring(struct be_ctrl_info *ctrl) | |||
| 79 | if (status != 0) | 206 | if (status != 0) |
| 80 | return status; | 207 | return status; |
| 81 | 208 | ||
| 82 | /* compl entry has been made now */ | 209 | /* A cq entry has been made now */ |
| 83 | be_dws_le_to_cpu(cqe, sizeof(*cqe)); | 210 | if (be_mcc_compl_is_new(cqe)) { |
| 84 | if (!(cqe->flags & CQE_FLAGS_VALID_MASK)) { | 211 | status = be_mcc_compl_process(ctrl, &mbox->cqe); |
| 85 | printk(KERN_WARNING DRV_NAME ": ERROR invalid mbox compl\n"); | 212 | be_mcc_compl_use(cqe); |
| 213 | if (status) | ||
| 214 | return status; | ||
| 215 | } else { | ||
| 216 | printk(KERN_WARNING DRV_NAME "invalid mailbox completion\n"); | ||
| 86 | return -1; | 217 | return -1; |
| 87 | } | 218 | } |
| 88 | 219 | return 0; | |
| 89 | compl_status = (cqe->status >> CQE_STATUS_COMPL_SHIFT) & | ||
| 90 | CQE_STATUS_COMPL_MASK; | ||
| 91 | if (compl_status != MCC_STATUS_SUCCESS) { | ||
| 92 | extd_status = (cqe->status >> CQE_STATUS_EXTD_SHIFT) & | ||
| 93 | CQE_STATUS_EXTD_MASK; | ||
| 94 | printk(KERN_WARNING DRV_NAME | ||
| 95 | ": ERROR in cmd compl. status(compl/extd)=%d/%d\n", | ||
| 96 | compl_status, extd_status); | ||
| 97 | } | ||
| 98 | |||
| 99 | return compl_status; | ||
| 100 | } | 220 | } |
| 101 | 221 | ||
| 102 | static int be_POST_stage_get(struct be_ctrl_info *ctrl, u16 *stage) | 222 | static int be_POST_stage_get(struct be_ctrl_info *ctrl, u16 *stage) |
| @@ -235,6 +355,18 @@ static inline struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem) | |||
| 235 | return &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb; | 355 | return &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb; |
| 236 | } | 356 | } |
| 237 | 357 | ||
| 358 | static inline struct be_mcc_wrb *wrb_from_mcc(struct be_queue_info *mccq) | ||
| 359 | { | ||
| 360 | struct be_mcc_wrb *wrb = NULL; | ||
| 361 | if (atomic_read(&mccq->used) < mccq->len) { | ||
| 362 | wrb = queue_head_node(mccq); | ||
| 363 | queue_head_inc(mccq); | ||
| 364 | atomic_inc(&mccq->used); | ||
| 365 | memset(wrb, 0, sizeof(*wrb)); | ||
| 366 | } | ||
| 367 | return wrb; | ||
| 368 | } | ||
| 369 | |||
| 238 | int be_cmd_eq_create(struct be_ctrl_info *ctrl, | 370 | int be_cmd_eq_create(struct be_ctrl_info *ctrl, |
| 239 | struct be_queue_info *eq, int eq_delay) | 371 | struct be_queue_info *eq, int eq_delay) |
| 240 | { | 372 | { |
| @@ -244,7 +376,7 @@ int be_cmd_eq_create(struct be_ctrl_info *ctrl, | |||
| 244 | struct be_dma_mem *q_mem = &eq->dma_mem; | 376 | struct be_dma_mem *q_mem = &eq->dma_mem; |
| 245 | int status; | 377 | int status; |
| 246 | 378 | ||
| 247 | spin_lock(&ctrl->cmd_lock); | 379 | spin_lock(&ctrl->mbox_lock); |
| 248 | memset(wrb, 0, sizeof(*wrb)); | 380 | memset(wrb, 0, sizeof(*wrb)); |
| 249 | 381 | ||
| 250 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 382 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
| @@ -272,7 +404,7 @@ int be_cmd_eq_create(struct be_ctrl_info *ctrl, | |||
| 272 | eq->id = le16_to_cpu(resp->eq_id); | 404 | eq->id = le16_to_cpu(resp->eq_id); |
| 273 | eq->created = true; | 405 | eq->created = true; |
| 274 | } | 406 | } |
| 275 | spin_unlock(&ctrl->cmd_lock); | 407 | spin_unlock(&ctrl->mbox_lock); |
| 276 | return status; | 408 | return status; |
| 277 | } | 409 | } |
| 278 | 410 | ||
| @@ -284,7 +416,7 @@ int be_cmd_mac_addr_query(struct be_ctrl_info *ctrl, u8 *mac_addr, | |||
| 284 | struct be_cmd_resp_mac_query *resp = embedded_payload(wrb); | 416 | struct be_cmd_resp_mac_query *resp = embedded_payload(wrb); |
| 285 | int status; | 417 | int status; |
| 286 | 418 | ||
| 287 | spin_lock(&ctrl->cmd_lock); | 419 | spin_lock(&ctrl->mbox_lock); |
| 288 | memset(wrb, 0, sizeof(*wrb)); | 420 | memset(wrb, 0, sizeof(*wrb)); |
| 289 | 421 | ||
| 290 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 422 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
| @@ -304,7 +436,7 @@ int be_cmd_mac_addr_query(struct be_ctrl_info *ctrl, u8 *mac_addr, | |||
| 304 | if (!status) | 436 | if (!status) |
| 305 | memcpy(mac_addr, resp->mac.addr, ETH_ALEN); | 437 | memcpy(mac_addr, resp->mac.addr, ETH_ALEN); |
| 306 | 438 | ||
| 307 | spin_unlock(&ctrl->cmd_lock); | 439 | spin_unlock(&ctrl->mbox_lock); |
| 308 | return status; | 440 | return status; |
| 309 | } | 441 | } |
| 310 | 442 | ||
| @@ -315,7 +447,7 @@ int be_cmd_pmac_add(struct be_ctrl_info *ctrl, u8 *mac_addr, | |||
| 315 | struct be_cmd_req_pmac_add *req = embedded_payload(wrb); | 447 | struct be_cmd_req_pmac_add *req = embedded_payload(wrb); |
| 316 | int status; | 448 | int status; |
| 317 | 449 | ||
| 318 | spin_lock(&ctrl->cmd_lock); | 450 | spin_lock(&ctrl->mbox_lock); |
| 319 | memset(wrb, 0, sizeof(*wrb)); | 451 | memset(wrb, 0, sizeof(*wrb)); |
| 320 | 452 | ||
| 321 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 453 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
| @@ -332,7 +464,7 @@ int be_cmd_pmac_add(struct be_ctrl_info *ctrl, u8 *mac_addr, | |||
| 332 | *pmac_id = le32_to_cpu(resp->pmac_id); | 464 | *pmac_id = le32_to_cpu(resp->pmac_id); |
| 333 | } | 465 | } |
| 334 | 466 | ||
| 335 | spin_unlock(&ctrl->cmd_lock); | 467 | spin_unlock(&ctrl->mbox_lock); |
| 336 | return status; | 468 | return status; |
| 337 | } | 469 | } |
| 338 | 470 | ||
| @@ -342,7 +474,7 @@ int be_cmd_pmac_del(struct be_ctrl_info *ctrl, u32 if_id, u32 pmac_id) | |||
| 342 | struct be_cmd_req_pmac_del *req = embedded_payload(wrb); | 474 | struct be_cmd_req_pmac_del *req = embedded_payload(wrb); |
| 343 | int status; | 475 | int status; |
| 344 | 476 | ||
| 345 | spin_lock(&ctrl->cmd_lock); | 477 | spin_lock(&ctrl->mbox_lock); |
| 346 | memset(wrb, 0, sizeof(*wrb)); | 478 | memset(wrb, 0, sizeof(*wrb)); |
| 347 | 479 | ||
| 348 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 480 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
| @@ -354,7 +486,7 @@ int be_cmd_pmac_del(struct be_ctrl_info *ctrl, u32 if_id, u32 pmac_id) | |||
| 354 | req->pmac_id = cpu_to_le32(pmac_id); | 486 | req->pmac_id = cpu_to_le32(pmac_id); |
| 355 | 487 | ||
| 356 | status = be_mbox_db_ring(ctrl); | 488 | status = be_mbox_db_ring(ctrl); |
| 357 | spin_unlock(&ctrl->cmd_lock); | 489 | spin_unlock(&ctrl->mbox_lock); |
| 358 | 490 | ||
| 359 | return status; | 491 | return status; |
| 360 | } | 492 | } |
| @@ -370,7 +502,7 @@ int be_cmd_cq_create(struct be_ctrl_info *ctrl, | |||
| 370 | void *ctxt = &req->context; | 502 | void *ctxt = &req->context; |
| 371 | int status; | 503 | int status; |
| 372 | 504 | ||
| 373 | spin_lock(&ctrl->cmd_lock); | 505 | spin_lock(&ctrl->mbox_lock); |
| 374 | memset(wrb, 0, sizeof(*wrb)); | 506 | memset(wrb, 0, sizeof(*wrb)); |
| 375 | 507 | ||
| 376 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 508 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
| @@ -388,7 +520,7 @@ int be_cmd_cq_create(struct be_ctrl_info *ctrl, | |||
| 388 | AMAP_SET_BITS(struct amap_cq_context, solevent, ctxt, sol_evts); | 520 | AMAP_SET_BITS(struct amap_cq_context, solevent, ctxt, sol_evts); |
| 389 | AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1); | 521 | AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1); |
| 390 | AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id); | 522 | AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id); |
| 391 | AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 0); | 523 | AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 1); |
| 392 | AMAP_SET_BITS(struct amap_cq_context, func, ctxt, ctrl->pci_func); | 524 | AMAP_SET_BITS(struct amap_cq_context, func, ctxt, ctrl->pci_func); |
| 393 | be_dws_cpu_to_le(ctxt, sizeof(req->context)); | 525 | be_dws_cpu_to_le(ctxt, sizeof(req->context)); |
| 394 | 526 | ||
| @@ -399,7 +531,56 @@ int be_cmd_cq_create(struct be_ctrl_info *ctrl, | |||
| 399 | cq->id = le16_to_cpu(resp->cq_id); | 531 | cq->id = le16_to_cpu(resp->cq_id); |
| 400 | cq->created = true; | 532 | cq->created = true; |
| 401 | } | 533 | } |
| 402 | spin_unlock(&ctrl->cmd_lock); | 534 | spin_unlock(&ctrl->mbox_lock); |
| 535 | |||
| 536 | return status; | ||
| 537 | } | ||
| 538 | |||
| 539 | static u32 be_encoded_q_len(int q_len) | ||
| 540 | { | ||
| 541 | u32 len_encoded = fls(q_len); /* log2(len) + 1 */ | ||
| 542 | if (len_encoded == 16) | ||
| 543 | len_encoded = 0; | ||
| 544 | return len_encoded; | ||
| 545 | } | ||
| 546 | |||
| 547 | int be_cmd_mccq_create(struct be_ctrl_info *ctrl, | ||
| 548 | struct be_queue_info *mccq, | ||
| 549 | struct be_queue_info *cq) | ||
| 550 | { | ||
| 551 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
| 552 | struct be_cmd_req_mcc_create *req = embedded_payload(wrb); | ||
| 553 | struct be_dma_mem *q_mem = &mccq->dma_mem; | ||
| 554 | void *ctxt = &req->context; | ||
| 555 | int status; | ||
| 556 | |||
| 557 | spin_lock(&ctrl->mbox_lock); | ||
| 558 | memset(wrb, 0, sizeof(*wrb)); | ||
| 559 | |||
| 560 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
| 561 | |||
| 562 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | ||
| 563 | OPCODE_COMMON_MCC_CREATE, sizeof(*req)); | ||
| 564 | |||
| 565 | req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); | ||
| 566 | |||
| 567 | AMAP_SET_BITS(struct amap_mcc_context, fid, ctxt, ctrl->pci_func); | ||
| 568 | AMAP_SET_BITS(struct amap_mcc_context, valid, ctxt, 1); | ||
| 569 | AMAP_SET_BITS(struct amap_mcc_context, ring_size, ctxt, | ||
| 570 | be_encoded_q_len(mccq->len)); | ||
| 571 | AMAP_SET_BITS(struct amap_mcc_context, cq_id, ctxt, cq->id); | ||
| 572 | |||
| 573 | be_dws_cpu_to_le(ctxt, sizeof(req->context)); | ||
| 574 | |||
| 575 | be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); | ||
| 576 | |||
| 577 | status = be_mbox_db_ring(ctrl); | ||
| 578 | if (!status) { | ||
| 579 | struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb); | ||
| 580 | mccq->id = le16_to_cpu(resp->id); | ||
| 581 | mccq->created = true; | ||
| 582 | } | ||
| 583 | spin_unlock(&ctrl->mbox_lock); | ||
| 403 | 584 | ||
| 404 | return status; | 585 | return status; |
| 405 | } | 586 | } |
| @@ -415,7 +596,7 @@ int be_cmd_txq_create(struct be_ctrl_info *ctrl, | |||
| 415 | int status; | 596 | int status; |
| 416 | u32 len_encoded; | 597 | u32 len_encoded; |
| 417 | 598 | ||
| 418 | spin_lock(&ctrl->cmd_lock); | 599 | spin_lock(&ctrl->mbox_lock); |
| 419 | memset(wrb, 0, sizeof(*wrb)); | 600 | memset(wrb, 0, sizeof(*wrb)); |
| 420 | 601 | ||
| 421 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 602 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
| @@ -446,7 +627,7 @@ int be_cmd_txq_create(struct be_ctrl_info *ctrl, | |||
| 446 | txq->id = le16_to_cpu(resp->cid); | 627 | txq->id = le16_to_cpu(resp->cid); |
| 447 | txq->created = true; | 628 | txq->created = true; |
| 448 | } | 629 | } |
| 449 | spin_unlock(&ctrl->cmd_lock); | 630 | spin_unlock(&ctrl->mbox_lock); |
| 450 | 631 | ||
| 451 | return status; | 632 | return status; |
| 452 | } | 633 | } |
| @@ -460,7 +641,7 @@ int be_cmd_rxq_create(struct be_ctrl_info *ctrl, | |||
| 460 | struct be_dma_mem *q_mem = &rxq->dma_mem; | 641 | struct be_dma_mem *q_mem = &rxq->dma_mem; |
| 461 | int status; | 642 | int status; |
| 462 | 643 | ||
| 463 | spin_lock(&ctrl->cmd_lock); | 644 | spin_lock(&ctrl->mbox_lock); |
| 464 | memset(wrb, 0, sizeof(*wrb)); | 645 | memset(wrb, 0, sizeof(*wrb)); |
| 465 | 646 | ||
| 466 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 647 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
| @@ -482,7 +663,7 @@ int be_cmd_rxq_create(struct be_ctrl_info *ctrl, | |||
| 482 | rxq->id = le16_to_cpu(resp->id); | 663 | rxq->id = le16_to_cpu(resp->id); |
| 483 | rxq->created = true; | 664 | rxq->created = true; |
| 484 | } | 665 | } |
| 485 | spin_unlock(&ctrl->cmd_lock); | 666 | spin_unlock(&ctrl->mbox_lock); |
| 486 | 667 | ||
| 487 | return status; | 668 | return status; |
| 488 | } | 669 | } |
| @@ -496,7 +677,7 @@ int be_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, | |||
| 496 | u8 subsys = 0, opcode = 0; | 677 | u8 subsys = 0, opcode = 0; |
| 497 | int status; | 678 | int status; |
| 498 | 679 | ||
| 499 | spin_lock(&ctrl->cmd_lock); | 680 | spin_lock(&ctrl->mbox_lock); |
| 500 | 681 | ||
| 501 | memset(wrb, 0, sizeof(*wrb)); | 682 | memset(wrb, 0, sizeof(*wrb)); |
| 502 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 683 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
| @@ -518,6 +699,10 @@ int be_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, | |||
| 518 | subsys = CMD_SUBSYSTEM_ETH; | 699 | subsys = CMD_SUBSYSTEM_ETH; |
| 519 | opcode = OPCODE_ETH_RX_DESTROY; | 700 | opcode = OPCODE_ETH_RX_DESTROY; |
| 520 | break; | 701 | break; |
| 702 | case QTYPE_MCCQ: | ||
| 703 | subsys = CMD_SUBSYSTEM_COMMON; | ||
| 704 | opcode = OPCODE_COMMON_MCC_DESTROY; | ||
| 705 | break; | ||
| 521 | default: | 706 | default: |
| 522 | printk(KERN_WARNING DRV_NAME ":bad Q type in Q destroy cmd\n"); | 707 | printk(KERN_WARNING DRV_NAME ":bad Q type in Q destroy cmd\n"); |
| 523 | status = -1; | 708 | status = -1; |
| @@ -528,7 +713,7 @@ int be_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, | |||
| 528 | 713 | ||
| 529 | status = be_mbox_db_ring(ctrl); | 714 | status = be_mbox_db_ring(ctrl); |
| 530 | err: | 715 | err: |
| 531 | spin_unlock(&ctrl->cmd_lock); | 716 | spin_unlock(&ctrl->mbox_lock); |
| 532 | 717 | ||
| 533 | return status; | 718 | return status; |
| 534 | } | 719 | } |
| @@ -541,7 +726,7 @@ int be_cmd_if_create(struct be_ctrl_info *ctrl, u32 flags, u8 *mac, | |||
| 541 | struct be_cmd_req_if_create *req = embedded_payload(wrb); | 726 | struct be_cmd_req_if_create *req = embedded_payload(wrb); |
| 542 | int status; | 727 | int status; |
| 543 | 728 | ||
| 544 | spin_lock(&ctrl->cmd_lock); | 729 | spin_lock(&ctrl->mbox_lock); |
| 545 | memset(wrb, 0, sizeof(*wrb)); | 730 | memset(wrb, 0, sizeof(*wrb)); |
| 546 | 731 | ||
| 547 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 732 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
| @@ -562,7 +747,7 @@ int be_cmd_if_create(struct be_ctrl_info *ctrl, u32 flags, u8 *mac, | |||
| 562 | *pmac_id = le32_to_cpu(resp->pmac_id); | 747 | *pmac_id = le32_to_cpu(resp->pmac_id); |
| 563 | } | 748 | } |
| 564 | 749 | ||
| 565 | spin_unlock(&ctrl->cmd_lock); | 750 | spin_unlock(&ctrl->mbox_lock); |
| 566 | return status; | 751 | return status; |
| 567 | } | 752 | } |
| 568 | 753 | ||
| @@ -572,7 +757,7 @@ int be_cmd_if_destroy(struct be_ctrl_info *ctrl, u32 interface_id) | |||
| 572 | struct be_cmd_req_if_destroy *req = embedded_payload(wrb); | 757 | struct be_cmd_req_if_destroy *req = embedded_payload(wrb); |
| 573 | int status; | 758 | int status; |
| 574 | 759 | ||
| 575 | spin_lock(&ctrl->cmd_lock); | 760 | spin_lock(&ctrl->mbox_lock); |
| 576 | memset(wrb, 0, sizeof(*wrb)); | 761 | memset(wrb, 0, sizeof(*wrb)); |
| 577 | 762 | ||
| 578 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 763 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
| @@ -583,7 +768,7 @@ int be_cmd_if_destroy(struct be_ctrl_info *ctrl, u32 interface_id) | |||
| 583 | req->interface_id = cpu_to_le32(interface_id); | 768 | req->interface_id = cpu_to_le32(interface_id); |
| 584 | status = be_mbox_db_ring(ctrl); | 769 | status = be_mbox_db_ring(ctrl); |
| 585 | 770 | ||
| 586 | spin_unlock(&ctrl->cmd_lock); | 771 | spin_unlock(&ctrl->mbox_lock); |
| 587 | 772 | ||
| 588 | return status; | 773 | return status; |
| 589 | } | 774 | } |
| @@ -598,7 +783,7 @@ int be_cmd_get_stats(struct be_ctrl_info *ctrl, struct be_dma_mem *nonemb_cmd) | |||
| 598 | struct be_sge *sge = nonembedded_sgl(wrb); | 783 | struct be_sge *sge = nonembedded_sgl(wrb); |
| 599 | int status; | 784 | int status; |
| 600 | 785 | ||
| 601 | spin_lock(&ctrl->cmd_lock); | 786 | spin_lock(&ctrl->mbox_lock); |
| 602 | memset(wrb, 0, sizeof(*wrb)); | 787 | memset(wrb, 0, sizeof(*wrb)); |
| 603 | 788 | ||
| 604 | memset(req, 0, sizeof(*req)); | 789 | memset(req, 0, sizeof(*req)); |
| @@ -617,18 +802,20 @@ int be_cmd_get_stats(struct be_ctrl_info *ctrl, struct be_dma_mem *nonemb_cmd) | |||
| 617 | be_dws_le_to_cpu(&resp->hw_stats, sizeof(resp->hw_stats)); | 802 | be_dws_le_to_cpu(&resp->hw_stats, sizeof(resp->hw_stats)); |
| 618 | } | 803 | } |
| 619 | 804 | ||
| 620 | spin_unlock(&ctrl->cmd_lock); | 805 | spin_unlock(&ctrl->mbox_lock); |
| 621 | return status; | 806 | return status; |
| 622 | } | 807 | } |
| 623 | 808 | ||
| 624 | int be_cmd_link_status_query(struct be_ctrl_info *ctrl, | 809 | int be_cmd_link_status_query(struct be_ctrl_info *ctrl, |
| 625 | struct be_link_info *link) | 810 | bool *link_up) |
| 626 | { | 811 | { |
| 627 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | 812 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); |
| 628 | struct be_cmd_req_link_status *req = embedded_payload(wrb); | 813 | struct be_cmd_req_link_status *req = embedded_payload(wrb); |
| 629 | int status; | 814 | int status; |
| 630 | 815 | ||
| 631 | spin_lock(&ctrl->cmd_lock); | 816 | spin_lock(&ctrl->mbox_lock); |
| 817 | |||
| 818 | *link_up = false; | ||
| 632 | memset(wrb, 0, sizeof(*wrb)); | 819 | memset(wrb, 0, sizeof(*wrb)); |
| 633 | 820 | ||
| 634 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 821 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
| @@ -639,14 +826,11 @@ int be_cmd_link_status_query(struct be_ctrl_info *ctrl, | |||
| 639 | status = be_mbox_db_ring(ctrl); | 826 | status = be_mbox_db_ring(ctrl); |
| 640 | if (!status) { | 827 | if (!status) { |
| 641 | struct be_cmd_resp_link_status *resp = embedded_payload(wrb); | 828 | struct be_cmd_resp_link_status *resp = embedded_payload(wrb); |
| 642 | link->speed = resp->mac_speed; | 829 | if (resp->mac_speed != PHY_LINK_SPEED_ZERO) |
| 643 | link->duplex = resp->mac_duplex; | 830 | *link_up = true; |
| 644 | link->fault = resp->mac_fault; | ||
| 645 | } else { | ||
| 646 | link->speed = PHY_LINK_SPEED_ZERO; | ||
| 647 | } | 831 | } |
| 648 | 832 | ||
| 649 | spin_unlock(&ctrl->cmd_lock); | 833 | spin_unlock(&ctrl->mbox_lock); |
| 650 | return status; | 834 | return status; |
| 651 | } | 835 | } |
| 652 | 836 | ||
| @@ -656,7 +840,7 @@ int be_cmd_get_fw_ver(struct be_ctrl_info *ctrl, char *fw_ver) | |||
| 656 | struct be_cmd_req_get_fw_version *req = embedded_payload(wrb); | 840 | struct be_cmd_req_get_fw_version *req = embedded_payload(wrb); |
| 657 | int status; | 841 | int status; |
| 658 | 842 | ||
| 659 | spin_lock(&ctrl->cmd_lock); | 843 | spin_lock(&ctrl->mbox_lock); |
| 660 | memset(wrb, 0, sizeof(*wrb)); | 844 | memset(wrb, 0, sizeof(*wrb)); |
| 661 | 845 | ||
| 662 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 846 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
| @@ -670,7 +854,7 @@ int be_cmd_get_fw_ver(struct be_ctrl_info *ctrl, char *fw_ver) | |||
| 670 | strncpy(fw_ver, resp->firmware_version_string, FW_VER_LEN); | 854 | strncpy(fw_ver, resp->firmware_version_string, FW_VER_LEN); |
| 671 | } | 855 | } |
| 672 | 856 | ||
| 673 | spin_unlock(&ctrl->cmd_lock); | 857 | spin_unlock(&ctrl->mbox_lock); |
| 674 | return status; | 858 | return status; |
| 675 | } | 859 | } |
| 676 | 860 | ||
| @@ -681,7 +865,7 @@ int be_cmd_modify_eqd(struct be_ctrl_info *ctrl, u32 eq_id, u32 eqd) | |||
| 681 | struct be_cmd_req_modify_eq_delay *req = embedded_payload(wrb); | 865 | struct be_cmd_req_modify_eq_delay *req = embedded_payload(wrb); |
| 682 | int status; | 866 | int status; |
| 683 | 867 | ||
| 684 | spin_lock(&ctrl->cmd_lock); | 868 | spin_lock(&ctrl->mbox_lock); |
| 685 | memset(wrb, 0, sizeof(*wrb)); | 869 | memset(wrb, 0, sizeof(*wrb)); |
| 686 | 870 | ||
| 687 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 871 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
| @@ -696,7 +880,7 @@ int be_cmd_modify_eqd(struct be_ctrl_info *ctrl, u32 eq_id, u32 eqd) | |||
| 696 | 880 | ||
| 697 | status = be_mbox_db_ring(ctrl); | 881 | status = be_mbox_db_ring(ctrl); |
| 698 | 882 | ||
| 699 | spin_unlock(&ctrl->cmd_lock); | 883 | spin_unlock(&ctrl->mbox_lock); |
| 700 | return status; | 884 | return status; |
| 701 | } | 885 | } |
| 702 | 886 | ||
| @@ -707,7 +891,7 @@ int be_cmd_vlan_config(struct be_ctrl_info *ctrl, u32 if_id, u16 *vtag_array, | |||
| 707 | struct be_cmd_req_vlan_config *req = embedded_payload(wrb); | 891 | struct be_cmd_req_vlan_config *req = embedded_payload(wrb); |
| 708 | int status; | 892 | int status; |
| 709 | 893 | ||
| 710 | spin_lock(&ctrl->cmd_lock); | 894 | spin_lock(&ctrl->mbox_lock); |
| 711 | memset(wrb, 0, sizeof(*wrb)); | 895 | memset(wrb, 0, sizeof(*wrb)); |
| 712 | 896 | ||
| 713 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 897 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
| @@ -726,18 +910,22 @@ int be_cmd_vlan_config(struct be_ctrl_info *ctrl, u32 if_id, u16 *vtag_array, | |||
| 726 | 910 | ||
| 727 | status = be_mbox_db_ring(ctrl); | 911 | status = be_mbox_db_ring(ctrl); |
| 728 | 912 | ||
| 729 | spin_unlock(&ctrl->cmd_lock); | 913 | spin_unlock(&ctrl->mbox_lock); |
| 730 | return status; | 914 | return status; |
| 731 | } | 915 | } |
| 732 | 916 | ||
| 917 | /* Use MCC for this command as it may be called in BH context */ | ||
| 733 | int be_cmd_promiscuous_config(struct be_ctrl_info *ctrl, u8 port_num, bool en) | 918 | int be_cmd_promiscuous_config(struct be_ctrl_info *ctrl, u8 port_num, bool en) |
| 734 | { | 919 | { |
| 735 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | 920 | struct be_mcc_wrb *wrb; |
| 736 | struct be_cmd_req_promiscuous_config *req = embedded_payload(wrb); | 921 | struct be_cmd_req_promiscuous_config *req; |
| 737 | int status; | ||
| 738 | 922 | ||
| 739 | spin_lock(&ctrl->cmd_lock); | 923 | spin_lock_bh(&ctrl->mcc_lock); |
| 740 | memset(wrb, 0, sizeof(*wrb)); | 924 | |
| 925 | wrb = wrb_from_mcc(&ctrl->mcc_obj.q); | ||
| 926 | BUG_ON(!wrb); | ||
| 927 | |||
| 928 | req = embedded_payload(wrb); | ||
| 741 | 929 | ||
| 742 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 930 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
| 743 | 931 | ||
| @@ -749,21 +937,29 @@ int be_cmd_promiscuous_config(struct be_ctrl_info *ctrl, u8 port_num, bool en) | |||
| 749 | else | 937 | else |
| 750 | req->port0_promiscuous = en; | 938 | req->port0_promiscuous = en; |
| 751 | 939 | ||
| 752 | status = be_mbox_db_ring(ctrl); | 940 | be_mcc_notify_wait(ctrl); |
| 753 | 941 | ||
| 754 | spin_unlock(&ctrl->cmd_lock); | 942 | spin_unlock_bh(&ctrl->mcc_lock); |
| 755 | return status; | 943 | return 0; |
| 756 | } | 944 | } |
| 757 | 945 | ||
| 758 | int be_cmd_mcast_mac_set(struct be_ctrl_info *ctrl, u32 if_id, u8 *mac_table, | 946 | /* |
| 759 | u32 num, bool promiscuous) | 947 | * Use MCC for this command as it may be called in BH context |
| 948 | * (mc == NULL) => multicast promiscous | ||
| 949 | */ | ||
| 950 | int be_cmd_multicast_set(struct be_ctrl_info *ctrl, u32 if_id, | ||
| 951 | struct dev_mc_list *mc_list, u32 mc_count) | ||
| 760 | { | 952 | { |
| 761 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | 953 | #define BE_MAX_MC 32 /* set mcast promisc if > 32 */ |
| 762 | struct be_cmd_req_mcast_mac_config *req = embedded_payload(wrb); | 954 | struct be_mcc_wrb *wrb; |
| 763 | int status; | 955 | struct be_cmd_req_mcast_mac_config *req; |
| 764 | 956 | ||
| 765 | spin_lock(&ctrl->cmd_lock); | 957 | spin_lock_bh(&ctrl->mcc_lock); |
| 766 | memset(wrb, 0, sizeof(*wrb)); | 958 | |
| 959 | wrb = wrb_from_mcc(&ctrl->mcc_obj.q); | ||
| 960 | BUG_ON(!wrb); | ||
| 961 | |||
| 962 | req = embedded_payload(wrb); | ||
| 767 | 963 | ||
| 768 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 964 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
| 769 | 965 | ||
| @@ -771,17 +967,23 @@ int be_cmd_mcast_mac_set(struct be_ctrl_info *ctrl, u32 if_id, u8 *mac_table, | |||
| 771 | OPCODE_COMMON_NTWK_MULTICAST_SET, sizeof(*req)); | 967 | OPCODE_COMMON_NTWK_MULTICAST_SET, sizeof(*req)); |
| 772 | 968 | ||
| 773 | req->interface_id = if_id; | 969 | req->interface_id = if_id; |
| 774 | req->promiscuous = promiscuous; | 970 | if (mc_list && mc_count <= BE_MAX_MC) { |
| 775 | if (!promiscuous) { | 971 | int i; |
| 776 | req->num_mac = cpu_to_le16(num); | 972 | struct dev_mc_list *mc; |
| 777 | if (num) | 973 | |
| 778 | memcpy(req->mac, mac_table, ETH_ALEN * num); | 974 | req->num_mac = cpu_to_le16(mc_count); |
| 975 | |||
| 976 | for (mc = mc_list, i = 0; mc; mc = mc->next, i++) | ||
| 977 | memcpy(req->mac[i].byte, mc->dmi_addr, ETH_ALEN); | ||
| 978 | } else { | ||
| 979 | req->promiscuous = 1; | ||
| 779 | } | 980 | } |
| 780 | 981 | ||
| 781 | status = be_mbox_db_ring(ctrl); | 982 | be_mcc_notify_wait(ctrl); |
| 782 | 983 | ||
| 783 | spin_unlock(&ctrl->cmd_lock); | 984 | spin_unlock_bh(&ctrl->mcc_lock); |
| 784 | return status; | 985 | |
| 986 | return 0; | ||
| 785 | } | 987 | } |
| 786 | 988 | ||
| 787 | int be_cmd_set_flow_control(struct be_ctrl_info *ctrl, u32 tx_fc, u32 rx_fc) | 989 | int be_cmd_set_flow_control(struct be_ctrl_info *ctrl, u32 tx_fc, u32 rx_fc) |
| @@ -790,7 +992,7 @@ int be_cmd_set_flow_control(struct be_ctrl_info *ctrl, u32 tx_fc, u32 rx_fc) | |||
| 790 | struct be_cmd_req_set_flow_control *req = embedded_payload(wrb); | 992 | struct be_cmd_req_set_flow_control *req = embedded_payload(wrb); |
| 791 | int status; | 993 | int status; |
| 792 | 994 | ||
| 793 | spin_lock(&ctrl->cmd_lock); | 995 | spin_lock(&ctrl->mbox_lock); |
| 794 | 996 | ||
| 795 | memset(wrb, 0, sizeof(*wrb)); | 997 | memset(wrb, 0, sizeof(*wrb)); |
| 796 | 998 | ||
| @@ -804,7 +1006,7 @@ int be_cmd_set_flow_control(struct be_ctrl_info *ctrl, u32 tx_fc, u32 rx_fc) | |||
| 804 | 1006 | ||
| 805 | status = be_mbox_db_ring(ctrl); | 1007 | status = be_mbox_db_ring(ctrl); |
| 806 | 1008 | ||
| 807 | spin_unlock(&ctrl->cmd_lock); | 1009 | spin_unlock(&ctrl->mbox_lock); |
| 808 | return status; | 1010 | return status; |
| 809 | } | 1011 | } |
| 810 | 1012 | ||
| @@ -814,7 +1016,7 @@ int be_cmd_get_flow_control(struct be_ctrl_info *ctrl, u32 *tx_fc, u32 *rx_fc) | |||
| 814 | struct be_cmd_req_get_flow_control *req = embedded_payload(wrb); | 1016 | struct be_cmd_req_get_flow_control *req = embedded_payload(wrb); |
| 815 | int status; | 1017 | int status; |
| 816 | 1018 | ||
| 817 | spin_lock(&ctrl->cmd_lock); | 1019 | spin_lock(&ctrl->mbox_lock); |
| 818 | 1020 | ||
| 819 | memset(wrb, 0, sizeof(*wrb)); | 1021 | memset(wrb, 0, sizeof(*wrb)); |
| 820 | 1022 | ||
| @@ -831,7 +1033,7 @@ int be_cmd_get_flow_control(struct be_ctrl_info *ctrl, u32 *tx_fc, u32 *rx_fc) | |||
| 831 | *rx_fc = le16_to_cpu(resp->rx_flow_control); | 1033 | *rx_fc = le16_to_cpu(resp->rx_flow_control); |
| 832 | } | 1034 | } |
| 833 | 1035 | ||
| 834 | spin_unlock(&ctrl->cmd_lock); | 1036 | spin_unlock(&ctrl->mbox_lock); |
| 835 | return status; | 1037 | return status; |
| 836 | } | 1038 | } |
| 837 | 1039 | ||
| @@ -841,7 +1043,7 @@ int be_cmd_query_fw_cfg(struct be_ctrl_info *ctrl, u32 *port_num) | |||
| 841 | struct be_cmd_req_query_fw_cfg *req = embedded_payload(wrb); | 1043 | struct be_cmd_req_query_fw_cfg *req = embedded_payload(wrb); |
| 842 | int status; | 1044 | int status; |
| 843 | 1045 | ||
| 844 | spin_lock(&ctrl->cmd_lock); | 1046 | spin_lock(&ctrl->mbox_lock); |
| 845 | 1047 | ||
| 846 | memset(wrb, 0, sizeof(*wrb)); | 1048 | memset(wrb, 0, sizeof(*wrb)); |
| 847 | 1049 | ||
| @@ -856,6 +1058,6 @@ int be_cmd_query_fw_cfg(struct be_ctrl_info *ctrl, u32 *port_num) | |||
| 856 | *port_num = le32_to_cpu(resp->phys_port); | 1058 | *port_num = le32_to_cpu(resp->phys_port); |
| 857 | } | 1059 | } |
| 858 | 1060 | ||
| 859 | spin_unlock(&ctrl->cmd_lock); | 1061 | spin_unlock(&ctrl->mbox_lock); |
| 860 | return status; | 1062 | return status; |
| 861 | } | 1063 | } |
diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index e499e2d5b8c3..747626da7b4e 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h | |||
| @@ -76,6 +76,34 @@ struct be_mcc_cq_entry { | |||
| 76 | u32 flags; /* dword 3 */ | 76 | u32 flags; /* dword 3 */ |
| 77 | }; | 77 | }; |
| 78 | 78 | ||
| 79 | /* When the async bit of mcc_compl is set, the last 4 bytes of | ||
| 80 | * mcc_compl is interpreted as follows: | ||
| 81 | */ | ||
| 82 | #define ASYNC_TRAILER_EVENT_CODE_SHIFT 8 /* bits 8 - 15 */ | ||
| 83 | #define ASYNC_TRAILER_EVENT_CODE_MASK 0xFF | ||
| 84 | #define ASYNC_EVENT_CODE_LINK_STATE 0x1 | ||
| 85 | struct be_async_event_trailer { | ||
| 86 | u32 code; | ||
| 87 | }; | ||
| 88 | |||
| 89 | enum { | ||
| 90 | ASYNC_EVENT_LINK_DOWN = 0x0, | ||
| 91 | ASYNC_EVENT_LINK_UP = 0x1 | ||
| 92 | }; | ||
| 93 | |||
| 94 | /* When the event code of an async trailer is link-state, the mcc_compl | ||
| 95 | * must be interpreted as follows | ||
| 96 | */ | ||
| 97 | struct be_async_event_link_state { | ||
| 98 | u8 physical_port; | ||
| 99 | u8 port_link_status; | ||
| 100 | u8 port_duplex; | ||
| 101 | u8 port_speed; | ||
| 102 | u8 port_fault; | ||
| 103 | u8 rsvd0[7]; | ||
| 104 | struct be_async_event_trailer trailer; | ||
| 105 | } __packed; | ||
| 106 | |||
| 79 | struct be_mcc_mailbox { | 107 | struct be_mcc_mailbox { |
| 80 | struct be_mcc_wrb wrb; | 108 | struct be_mcc_wrb wrb; |
| 81 | struct be_mcc_cq_entry cqe; | 109 | struct be_mcc_cq_entry cqe; |
| @@ -101,6 +129,7 @@ struct be_mcc_mailbox { | |||
| 101 | #define OPCODE_COMMON_FIRMWARE_CONFIG 42 | 129 | #define OPCODE_COMMON_FIRMWARE_CONFIG 42 |
| 102 | #define OPCODE_COMMON_NTWK_INTERFACE_CREATE 50 | 130 | #define OPCODE_COMMON_NTWK_INTERFACE_CREATE 50 |
| 103 | #define OPCODE_COMMON_NTWK_INTERFACE_DESTROY 51 | 131 | #define OPCODE_COMMON_NTWK_INTERFACE_DESTROY 51 |
| 132 | #define OPCODE_COMMON_MCC_DESTROY 53 | ||
| 104 | #define OPCODE_COMMON_CQ_DESTROY 54 | 133 | #define OPCODE_COMMON_CQ_DESTROY 54 |
| 105 | #define OPCODE_COMMON_EQ_DESTROY 55 | 134 | #define OPCODE_COMMON_EQ_DESTROY 55 |
| 106 | #define OPCODE_COMMON_QUERY_FIRMWARE_CONFIG 58 | 135 | #define OPCODE_COMMON_QUERY_FIRMWARE_CONFIG 58 |
| @@ -269,6 +298,38 @@ struct be_cmd_resp_cq_create { | |||
| 269 | u16 rsvd0; | 298 | u16 rsvd0; |
| 270 | } __packed; | 299 | } __packed; |
| 271 | 300 | ||
| 301 | /******************** Create MCCQ ***************************/ | ||
| 302 | /* Pseudo amap definition in which each bit of the actual structure is defined | ||
| 303 | * as a byte: used to calculate offset/shift/mask of each field */ | ||
| 304 | struct amap_mcc_context { | ||
| 305 | u8 con_index[14]; | ||
| 306 | u8 rsvd0[2]; | ||
| 307 | u8 ring_size[4]; | ||
| 308 | u8 fetch_wrb; | ||
| 309 | u8 fetch_r2t; | ||
| 310 | u8 cq_id[10]; | ||
| 311 | u8 prod_index[14]; | ||
| 312 | u8 fid[8]; | ||
| 313 | u8 pdid[9]; | ||
| 314 | u8 valid; | ||
| 315 | u8 rsvd1[32]; | ||
| 316 | u8 rsvd2[32]; | ||
| 317 | } __packed; | ||
| 318 | |||
| 319 | struct be_cmd_req_mcc_create { | ||
| 320 | struct be_cmd_req_hdr hdr; | ||
| 321 | u16 num_pages; | ||
| 322 | u16 rsvd0; | ||
| 323 | u8 context[sizeof(struct amap_mcc_context) / 8]; | ||
| 324 | struct phys_addr pages[8]; | ||
| 325 | } __packed; | ||
| 326 | |||
| 327 | struct be_cmd_resp_mcc_create { | ||
| 328 | struct be_cmd_resp_hdr hdr; | ||
| 329 | u16 id; | ||
| 330 | u16 rsvd0; | ||
| 331 | } __packed; | ||
| 332 | |||
| 272 | /******************** Create TxQ ***************************/ | 333 | /******************** Create TxQ ***************************/ |
| 273 | #define BE_ETH_TX_RING_TYPE_STANDARD 2 | 334 | #define BE_ETH_TX_RING_TYPE_STANDARD 2 |
| 274 | #define BE_ULP1_NUM 1 | 335 | #define BE_ULP1_NUM 1 |
| @@ -341,7 +402,8 @@ enum { | |||
| 341 | QTYPE_EQ = 1, | 402 | QTYPE_EQ = 1, |
| 342 | QTYPE_CQ, | 403 | QTYPE_CQ, |
| 343 | QTYPE_TXQ, | 404 | QTYPE_TXQ, |
| 344 | QTYPE_RXQ | 405 | QTYPE_RXQ, |
| 406 | QTYPE_MCCQ | ||
| 345 | }; | 407 | }; |
| 346 | 408 | ||
| 347 | struct be_cmd_req_q_destroy { | 409 | struct be_cmd_req_q_destroy { |
| @@ -546,12 +608,6 @@ struct be_cmd_req_link_status { | |||
| 546 | u32 rsvd; | 608 | u32 rsvd; |
| 547 | }; | 609 | }; |
| 548 | 610 | ||
| 549 | struct be_link_info { | ||
| 550 | u8 duplex; | ||
| 551 | u8 speed; | ||
| 552 | u8 fault; | ||
| 553 | }; | ||
| 554 | |||
| 555 | enum { | 611 | enum { |
| 556 | PHY_LINK_DUPLEX_NONE = 0x0, | 612 | PHY_LINK_DUPLEX_NONE = 0x0, |
| 557 | PHY_LINK_DUPLEX_HALF = 0x1, | 613 | PHY_LINK_DUPLEX_HALF = 0x1, |
| @@ -657,6 +713,9 @@ extern int be_cmd_cq_create(struct be_ctrl_info *ctrl, | |||
| 657 | struct be_queue_info *cq, struct be_queue_info *eq, | 713 | struct be_queue_info *cq, struct be_queue_info *eq, |
| 658 | bool sol_evts, bool no_delay, | 714 | bool sol_evts, bool no_delay, |
| 659 | int num_cqe_dma_coalesce); | 715 | int num_cqe_dma_coalesce); |
| 716 | extern int be_cmd_mccq_create(struct be_ctrl_info *ctrl, | ||
| 717 | struct be_queue_info *mccq, | ||
| 718 | struct be_queue_info *cq); | ||
| 660 | extern int be_cmd_txq_create(struct be_ctrl_info *ctrl, | 719 | extern int be_cmd_txq_create(struct be_ctrl_info *ctrl, |
| 661 | struct be_queue_info *txq, | 720 | struct be_queue_info *txq, |
| 662 | struct be_queue_info *cq); | 721 | struct be_queue_info *cq); |
| @@ -667,7 +726,7 @@ extern int be_cmd_rxq_create(struct be_ctrl_info *ctrl, | |||
| 667 | extern int be_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, | 726 | extern int be_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, |
| 668 | int type); | 727 | int type); |
| 669 | extern int be_cmd_link_status_query(struct be_ctrl_info *ctrl, | 728 | extern int be_cmd_link_status_query(struct be_ctrl_info *ctrl, |
| 670 | struct be_link_info *link); | 729 | bool *link_up); |
| 671 | extern int be_cmd_reset(struct be_ctrl_info *ctrl); | 730 | extern int be_cmd_reset(struct be_ctrl_info *ctrl); |
| 672 | extern int be_cmd_get_stats(struct be_ctrl_info *ctrl, | 731 | extern int be_cmd_get_stats(struct be_ctrl_info *ctrl, |
| 673 | struct be_dma_mem *nonemb_cmd); | 732 | struct be_dma_mem *nonemb_cmd); |
| @@ -679,10 +738,11 @@ extern int be_cmd_vlan_config(struct be_ctrl_info *ctrl, u32 if_id, | |||
| 679 | bool promiscuous); | 738 | bool promiscuous); |
| 680 | extern int be_cmd_promiscuous_config(struct be_ctrl_info *ctrl, | 739 | extern int be_cmd_promiscuous_config(struct be_ctrl_info *ctrl, |
| 681 | u8 port_num, bool en); | 740 | u8 port_num, bool en); |
| 682 | extern int be_cmd_mcast_mac_set(struct be_ctrl_info *ctrl, u32 if_id, | 741 | extern int be_cmd_multicast_set(struct be_ctrl_info *ctrl, u32 if_id, |
| 683 | u8 *mac_table, u32 num, bool promiscuous); | 742 | struct dev_mc_list *mc_list, u32 mc_count); |
| 684 | extern int be_cmd_set_flow_control(struct be_ctrl_info *ctrl, | 743 | extern int be_cmd_set_flow_control(struct be_ctrl_info *ctrl, |
| 685 | u32 tx_fc, u32 rx_fc); | 744 | u32 tx_fc, u32 rx_fc); |
| 686 | extern int be_cmd_get_flow_control(struct be_ctrl_info *ctrl, | 745 | extern int be_cmd_get_flow_control(struct be_ctrl_info *ctrl, |
| 687 | u32 *tx_fc, u32 *rx_fc); | 746 | u32 *tx_fc, u32 *rx_fc); |
| 688 | extern int be_cmd_query_fw_cfg(struct be_ctrl_info *ctrl, u32 *port_num); | 747 | extern int be_cmd_query_fw_cfg(struct be_ctrl_info *ctrl, u32 *port_num); |
| 748 | extern void be_process_mcc(struct be_ctrl_info *ctrl); | ||
diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h index b132aa4893ca..b02e805c1db3 100644 --- a/drivers/net/benet/be_hw.h +++ b/drivers/net/benet/be_hw.h | |||
| @@ -61,7 +61,7 @@ | |||
| 61 | /* Clear the interrupt for this eq */ | 61 | /* Clear the interrupt for this eq */ |
| 62 | #define DB_EQ_CLR_SHIFT (9) /* bit 9 */ | 62 | #define DB_EQ_CLR_SHIFT (9) /* bit 9 */ |
| 63 | /* Must be 1 */ | 63 | /* Must be 1 */ |
| 64 | #define DB_EQ_EVNT_SHIFT (10) /* bit 10 */ | 64 | #define DB_EQ_EVNT_SHIFT (10) /* bit 10 */ |
| 65 | /* Number of event entries processed */ | 65 | /* Number of event entries processed */ |
| 66 | #define DB_EQ_NUM_POPPED_SHIFT (16) /* bits 16 - 28 */ | 66 | #define DB_EQ_NUM_POPPED_SHIFT (16) /* bits 16 - 28 */ |
| 67 | /* Rearm bit */ | 67 | /* Rearm bit */ |
| @@ -88,6 +88,12 @@ | |||
| 88 | /* Number of rx frags posted */ | 88 | /* Number of rx frags posted */ |
| 89 | #define DB_RQ_NUM_POSTED_SHIFT (24) /* bits 24 - 31 */ | 89 | #define DB_RQ_NUM_POSTED_SHIFT (24) /* bits 24 - 31 */ |
| 90 | 90 | ||
| 91 | /********** MCC door bell ************/ | ||
| 92 | #define DB_MCCQ_OFFSET 0x140 | ||
| 93 | #define DB_MCCQ_RING_ID_MASK 0x7FF /* bits 0 - 10 */ | ||
| 94 | /* Number of entries posted */ | ||
| 95 | #define DB_MCCQ_NUM_POSTED_SHIFT (16) /* bits 16 - 29 */ | ||
| 96 | |||
| 91 | /* | 97 | /* |
| 92 | * BE descriptors: host memory data structures whose formats | 98 | * BE descriptors: host memory data structures whose formats |
| 93 | * are hardwired in BE silicon. | 99 | * are hardwired in BE silicon. |
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 66bb56874d9b..66c10c87f517 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c | |||
| @@ -60,26 +60,6 @@ static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q, | |||
| 60 | return 0; | 60 | return 0; |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | static inline void *queue_head_node(struct be_queue_info *q) | ||
| 64 | { | ||
| 65 | return q->dma_mem.va + q->head * q->entry_size; | ||
| 66 | } | ||
| 67 | |||
| 68 | static inline void *queue_tail_node(struct be_queue_info *q) | ||
| 69 | { | ||
| 70 | return q->dma_mem.va + q->tail * q->entry_size; | ||
| 71 | } | ||
| 72 | |||
| 73 | static inline void queue_head_inc(struct be_queue_info *q) | ||
| 74 | { | ||
| 75 | index_inc(&q->head, q->len); | ||
| 76 | } | ||
| 77 | |||
| 78 | static inline void queue_tail_inc(struct be_queue_info *q) | ||
| 79 | { | ||
| 80 | index_inc(&q->tail, q->len); | ||
| 81 | } | ||
| 82 | |||
| 83 | static void be_intr_set(struct be_ctrl_info *ctrl, bool enable) | 63 | static void be_intr_set(struct be_ctrl_info *ctrl, bool enable) |
| 84 | { | 64 | { |
| 85 | u8 __iomem *addr = ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET; | 65 | u8 __iomem *addr = ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET; |
| @@ -127,7 +107,7 @@ static void be_eq_notify(struct be_ctrl_info *ctrl, u16 qid, | |||
| 127 | iowrite32(val, ctrl->db + DB_EQ_OFFSET); | 107 | iowrite32(val, ctrl->db + DB_EQ_OFFSET); |
| 128 | } | 108 | } |
| 129 | 109 | ||
| 130 | static void be_cq_notify(struct be_ctrl_info *ctrl, u16 qid, | 110 | void be_cq_notify(struct be_ctrl_info *ctrl, u16 qid, |
| 131 | bool arm, u16 num_popped) | 111 | bool arm, u16 num_popped) |
| 132 | { | 112 | { |
| 133 | u32 val = 0; | 113 | u32 val = 0; |
| @@ -234,28 +214,24 @@ static void netdev_stats_update(struct be_adapter *adapter) | |||
| 234 | dev_stats->tx_window_errors = 0; | 214 | dev_stats->tx_window_errors = 0; |
| 235 | } | 215 | } |
| 236 | 216 | ||
| 237 | static void be_link_status_update(struct be_adapter *adapter) | 217 | void be_link_status_update(void *ctxt, bool link_up) |
| 238 | { | 218 | { |
| 239 | struct be_link_info *prev = &adapter->link; | 219 | struct be_adapter *adapter = ctxt; |
| 240 | struct be_link_info now = { 0 }; | ||
| 241 | struct net_device *netdev = adapter->netdev; | 220 | struct net_device *netdev = adapter->netdev; |
| 242 | 221 | ||
| 243 | be_cmd_link_status_query(&adapter->ctrl, &now); | ||
| 244 | |||
| 245 | /* If link came up or went down */ | 222 | /* If link came up or went down */ |
| 246 | if (now.speed != prev->speed && (now.speed == PHY_LINK_SPEED_ZERO || | 223 | if (adapter->link_up != link_up) { |
| 247 | prev->speed == PHY_LINK_SPEED_ZERO)) { | 224 | if (link_up) { |
| 248 | if (now.speed == PHY_LINK_SPEED_ZERO) { | ||
| 249 | netif_stop_queue(netdev); | ||
| 250 | netif_carrier_off(netdev); | ||
| 251 | printk(KERN_INFO "%s: Link down\n", netdev->name); | ||
| 252 | } else { | ||
| 253 | netif_start_queue(netdev); | 225 | netif_start_queue(netdev); |
| 254 | netif_carrier_on(netdev); | 226 | netif_carrier_on(netdev); |
| 255 | printk(KERN_INFO "%s: Link up\n", netdev->name); | 227 | printk(KERN_INFO "%s: Link up\n", netdev->name); |
| 228 | } else { | ||
| 229 | netif_stop_queue(netdev); | ||
| 230 | netif_carrier_off(netdev); | ||
| 231 | printk(KERN_INFO "%s: Link down\n", netdev->name); | ||
| 256 | } | 232 | } |
| 233 | adapter->link_up = link_up; | ||
| 257 | } | 234 | } |
| 258 | *prev = now; | ||
| 259 | } | 235 | } |
| 260 | 236 | ||
| 261 | /* Update the EQ delay n BE based on the RX frags consumed / sec */ | 237 | /* Update the EQ delay n BE based on the RX frags consumed / sec */ |
| @@ -569,47 +545,32 @@ static void be_vlan_rem_vid(struct net_device *netdev, u16 vid) | |||
| 569 | be_vid_config(netdev); | 545 | be_vid_config(netdev); |
| 570 | } | 546 | } |
| 571 | 547 | ||
| 572 | static void be_set_multicast_filter(struct net_device *netdev) | 548 | static void be_set_multicast_list(struct net_device *netdev) |
| 573 | { | 549 | { |
| 574 | struct be_adapter *adapter = netdev_priv(netdev); | 550 | struct be_adapter *adapter = netdev_priv(netdev); |
| 575 | struct dev_mc_list *mc_ptr; | 551 | struct be_ctrl_info *ctrl = &adapter->ctrl; |
| 576 | u8 mac_addr[32][ETH_ALEN]; | ||
| 577 | int i = 0; | ||
| 578 | 552 | ||
| 579 | if (netdev->flags & IFF_ALLMULTI) { | 553 | if (netdev->flags & IFF_PROMISC) { |
| 580 | /* set BE in Multicast promiscuous */ | 554 | be_cmd_promiscuous_config(ctrl, adapter->port_num, 1); |
| 581 | be_cmd_mcast_mac_set(&adapter->ctrl, | 555 | adapter->promiscuous = true; |
| 582 | adapter->if_handle, NULL, 0, true); | 556 | goto done; |
| 583 | return; | ||
| 584 | } | 557 | } |
| 585 | 558 | ||
| 586 | for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) { | 559 | /* BE was previously in promiscous mode; disable it */ |
| 587 | memcpy(&mac_addr[i][0], mc_ptr->dmi_addr, ETH_ALEN); | 560 | if (adapter->promiscuous) { |
| 588 | if (++i >= 32) { | 561 | adapter->promiscuous = false; |
| 589 | be_cmd_mcast_mac_set(&adapter->ctrl, | 562 | be_cmd_promiscuous_config(ctrl, adapter->port_num, 0); |
| 590 | adapter->if_handle, &mac_addr[0][0], i, false); | ||
| 591 | i = 0; | ||
| 592 | } | ||
| 593 | |||
| 594 | } | 563 | } |
| 595 | 564 | ||
| 596 | if (i) { | 565 | if (netdev->flags & IFF_ALLMULTI) { |
| 597 | /* reset the promiscuous mode also. */ | 566 | be_cmd_multicast_set(ctrl, adapter->if_handle, NULL, 0); |
| 598 | be_cmd_mcast_mac_set(&adapter->ctrl, | 567 | goto done; |
| 599 | adapter->if_handle, &mac_addr[0][0], i, false); | ||
| 600 | } | 568 | } |
| 601 | } | ||
| 602 | 569 | ||
| 603 | static void be_set_multicast_list(struct net_device *netdev) | 570 | be_cmd_multicast_set(ctrl, adapter->if_handle, netdev->mc_list, |
| 604 | { | 571 | netdev->mc_count); |
| 605 | struct be_adapter *adapter = netdev_priv(netdev); | 572 | done: |
| 606 | 573 | return; | |
| 607 | if (netdev->flags & IFF_PROMISC) { | ||
| 608 | be_cmd_promiscuous_config(&adapter->ctrl, adapter->port_num, 1); | ||
| 609 | } else { | ||
| 610 | be_cmd_promiscuous_config(&adapter->ctrl, adapter->port_num, 0); | ||
| 611 | be_set_multicast_filter(netdev); | ||
| 612 | } | ||
| 613 | } | 574 | } |
| 614 | 575 | ||
| 615 | static void be_rx_rate_update(struct be_adapter *adapter) | 576 | static void be_rx_rate_update(struct be_adapter *adapter) |
| @@ -960,10 +921,8 @@ static void be_post_rx_frags(struct be_adapter *adapter) | |||
| 960 | return; | 921 | return; |
| 961 | } | 922 | } |
| 962 | 923 | ||
| 963 | static struct be_eth_tx_compl * | 924 | static struct be_eth_tx_compl *be_tx_compl_get(struct be_queue_info *tx_cq) |
| 964 | be_tx_compl_get(struct be_adapter *adapter) | ||
| 965 | { | 925 | { |
| 966 | struct be_queue_info *tx_cq = &adapter->tx_obj.cq; | ||
| 967 | struct be_eth_tx_compl *txcp = queue_tail_node(tx_cq); | 926 | struct be_eth_tx_compl *txcp = queue_tail_node(tx_cq); |
| 968 | 927 | ||
| 969 | if (txcp->dw[offsetof(struct amap_eth_tx_compl, valid) / 32] == 0) | 928 | if (txcp->dw[offsetof(struct amap_eth_tx_compl, valid) / 32] == 0) |
| @@ -1051,6 +1010,59 @@ static void be_tx_q_clean(struct be_adapter *adapter) | |||
| 1051 | } | 1010 | } |
| 1052 | } | 1011 | } |
| 1053 | 1012 | ||
| 1013 | static void be_mcc_queues_destroy(struct be_adapter *adapter) | ||
| 1014 | { | ||
| 1015 | struct be_queue_info *q; | ||
| 1016 | struct be_ctrl_info *ctrl = &adapter->ctrl; | ||
| 1017 | |||
| 1018 | q = &ctrl->mcc_obj.q; | ||
| 1019 | if (q->created) | ||
| 1020 | be_cmd_q_destroy(ctrl, q, QTYPE_MCCQ); | ||
| 1021 | be_queue_free(adapter, q); | ||
| 1022 | |||
| 1023 | q = &ctrl->mcc_obj.cq; | ||
| 1024 | if (q->created) | ||
| 1025 | be_cmd_q_destroy(ctrl, q, QTYPE_CQ); | ||
| 1026 | be_queue_free(adapter, q); | ||
| 1027 | } | ||
| 1028 | |||
| 1029 | /* Must be called only after TX qs are created as MCC shares TX EQ */ | ||
| 1030 | static int be_mcc_queues_create(struct be_adapter *adapter) | ||
| 1031 | { | ||
| 1032 | struct be_queue_info *q, *cq; | ||
| 1033 | struct be_ctrl_info *ctrl = &adapter->ctrl; | ||
| 1034 | |||
| 1035 | /* Alloc MCC compl queue */ | ||
| 1036 | cq = &ctrl->mcc_obj.cq; | ||
| 1037 | if (be_queue_alloc(adapter, cq, MCC_CQ_LEN, | ||
| 1038 | sizeof(struct be_mcc_cq_entry))) | ||
| 1039 | goto err; | ||
| 1040 | |||
| 1041 | /* Ask BE to create MCC compl queue; share TX's eq */ | ||
| 1042 | if (be_cmd_cq_create(ctrl, cq, &adapter->tx_eq.q, false, true, 0)) | ||
| 1043 | goto mcc_cq_free; | ||
| 1044 | |||
| 1045 | /* Alloc MCC queue */ | ||
| 1046 | q = &ctrl->mcc_obj.q; | ||
| 1047 | if (be_queue_alloc(adapter, q, MCC_Q_LEN, sizeof(struct be_mcc_wrb))) | ||
| 1048 | goto mcc_cq_destroy; | ||
| 1049 | |||
| 1050 | /* Ask BE to create MCC queue */ | ||
| 1051 | if (be_cmd_mccq_create(ctrl, q, cq)) | ||
| 1052 | goto mcc_q_free; | ||
| 1053 | |||
| 1054 | return 0; | ||
| 1055 | |||
| 1056 | mcc_q_free: | ||
| 1057 | be_queue_free(adapter, q); | ||
| 1058 | mcc_cq_destroy: | ||
| 1059 | be_cmd_q_destroy(ctrl, cq, QTYPE_CQ); | ||
| 1060 | mcc_cq_free: | ||
| 1061 | be_queue_free(adapter, cq); | ||
| 1062 | err: | ||
| 1063 | return -1; | ||
| 1064 | } | ||
| 1065 | |||
| 1054 | static void be_tx_queues_destroy(struct be_adapter *adapter) | 1066 | static void be_tx_queues_destroy(struct be_adapter *adapter) |
| 1055 | { | 1067 | { |
| 1056 | struct be_queue_info *q; | 1068 | struct be_queue_info *q; |
| @@ -1263,7 +1275,7 @@ static irqreturn_t be_msix_rx(int irq, void *dev) | |||
| 1263 | return IRQ_HANDLED; | 1275 | return IRQ_HANDLED; |
| 1264 | } | 1276 | } |
| 1265 | 1277 | ||
| 1266 | static irqreturn_t be_msix_tx(int irq, void *dev) | 1278 | static irqreturn_t be_msix_tx_mcc(int irq, void *dev) |
| 1267 | { | 1279 | { |
| 1268 | struct be_adapter *adapter = dev; | 1280 | struct be_adapter *adapter = dev; |
| 1269 | 1281 | ||
| @@ -1324,40 +1336,51 @@ int be_poll_rx(struct napi_struct *napi, int budget) | |||
| 1324 | return work_done; | 1336 | return work_done; |
| 1325 | } | 1337 | } |
| 1326 | 1338 | ||
| 1327 | /* For TX we don't honour budget; consume everything */ | 1339 | void be_process_tx(struct be_adapter *adapter) |
| 1328 | int be_poll_tx(struct napi_struct *napi, int budget) | ||
| 1329 | { | 1340 | { |
| 1330 | struct be_eq_obj *tx_eq = container_of(napi, struct be_eq_obj, napi); | 1341 | struct be_queue_info *txq = &adapter->tx_obj.q; |
| 1331 | struct be_adapter *adapter = | 1342 | struct be_queue_info *tx_cq = &adapter->tx_obj.cq; |
| 1332 | container_of(tx_eq, struct be_adapter, tx_eq); | ||
| 1333 | struct be_tx_obj *tx_obj = &adapter->tx_obj; | ||
| 1334 | struct be_queue_info *tx_cq = &tx_obj->cq; | ||
| 1335 | struct be_queue_info *txq = &tx_obj->q; | ||
| 1336 | struct be_eth_tx_compl *txcp; | 1343 | struct be_eth_tx_compl *txcp; |
| 1337 | u32 num_cmpl = 0; | 1344 | u32 num_cmpl = 0; |
| 1338 | u16 end_idx; | 1345 | u16 end_idx; |
| 1339 | 1346 | ||
| 1340 | while ((txcp = be_tx_compl_get(adapter))) { | 1347 | while ((txcp = be_tx_compl_get(tx_cq))) { |
| 1341 | end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl, | 1348 | end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl, |
| 1342 | wrb_index, txcp); | 1349 | wrb_index, txcp); |
| 1343 | be_tx_compl_process(adapter, end_idx); | 1350 | be_tx_compl_process(adapter, end_idx); |
| 1344 | num_cmpl++; | 1351 | num_cmpl++; |
| 1345 | } | 1352 | } |
| 1346 | 1353 | ||
| 1347 | /* As Tx wrbs have been freed up, wake up netdev queue if | 1354 | if (num_cmpl) { |
| 1348 | * it was stopped due to lack of tx wrbs. | 1355 | be_cq_notify(&adapter->ctrl, tx_cq->id, true, num_cmpl); |
| 1349 | */ | 1356 | |
| 1350 | if (netif_queue_stopped(adapter->netdev) && | 1357 | /* As Tx wrbs have been freed up, wake up netdev queue if |
| 1358 | * it was stopped due to lack of tx wrbs. | ||
| 1359 | */ | ||
| 1360 | if (netif_queue_stopped(adapter->netdev) && | ||
| 1351 | atomic_read(&txq->used) < txq->len / 2) { | 1361 | atomic_read(&txq->used) < txq->len / 2) { |
| 1352 | netif_wake_queue(adapter->netdev); | 1362 | netif_wake_queue(adapter->netdev); |
| 1363 | } | ||
| 1364 | |||
| 1365 | drvr_stats(adapter)->be_tx_events++; | ||
| 1366 | drvr_stats(adapter)->be_tx_compl += num_cmpl; | ||
| 1353 | } | 1367 | } |
| 1368 | } | ||
| 1369 | |||
| 1370 | /* As TX and MCC share the same EQ check for both TX and MCC completions. | ||
| 1371 | * For TX/MCC we don't honour budget; consume everything | ||
| 1372 | */ | ||
| 1373 | static int be_poll_tx_mcc(struct napi_struct *napi, int budget) | ||
| 1374 | { | ||
| 1375 | struct be_eq_obj *tx_eq = container_of(napi, struct be_eq_obj, napi); | ||
| 1376 | struct be_adapter *adapter = | ||
| 1377 | container_of(tx_eq, struct be_adapter, tx_eq); | ||
| 1354 | 1378 | ||
| 1355 | napi_complete(napi); | 1379 | napi_complete(napi); |
| 1356 | 1380 | ||
| 1357 | be_cq_notify(&adapter->ctrl, tx_cq->id, true, num_cmpl); | 1381 | be_process_tx(adapter); |
| 1358 | 1382 | ||
| 1359 | drvr_stats(adapter)->be_tx_events++; | 1383 | be_process_mcc(&adapter->ctrl); |
| 1360 | drvr_stats(adapter)->be_tx_compl += num_cmpl; | ||
| 1361 | 1384 | ||
| 1362 | return 1; | 1385 | return 1; |
| 1363 | } | 1386 | } |
| @@ -1368,9 +1391,6 @@ static void be_worker(struct work_struct *work) | |||
| 1368 | container_of(work, struct be_adapter, work.work); | 1391 | container_of(work, struct be_adapter, work.work); |
| 1369 | int status; | 1392 | int status; |
| 1370 | 1393 | ||
| 1371 | /* Check link */ | ||
| 1372 | be_link_status_update(adapter); | ||
| 1373 | |||
| 1374 | /* Get Stats */ | 1394 | /* Get Stats */ |
| 1375 | status = be_cmd_get_stats(&adapter->ctrl, &adapter->stats.cmd); | 1395 | status = be_cmd_get_stats(&adapter->ctrl, &adapter->stats.cmd); |
| 1376 | if (!status) | 1396 | if (!status) |
| @@ -1419,7 +1439,7 @@ static int be_msix_register(struct be_adapter *adapter) | |||
| 1419 | 1439 | ||
| 1420 | sprintf(tx_eq->desc, "%s-tx", netdev->name); | 1440 | sprintf(tx_eq->desc, "%s-tx", netdev->name); |
| 1421 | vec = be_msix_vec_get(adapter, tx_eq->q.id); | 1441 | vec = be_msix_vec_get(adapter, tx_eq->q.id); |
| 1422 | status = request_irq(vec, be_msix_tx, 0, tx_eq->desc, adapter); | 1442 | status = request_irq(vec, be_msix_tx_mcc, 0, tx_eq->desc, adapter); |
| 1423 | if (status) | 1443 | if (status) |
| 1424 | goto err; | 1444 | goto err; |
| 1425 | 1445 | ||
| @@ -1495,6 +1515,39 @@ static int be_open(struct net_device *netdev) | |||
| 1495 | struct be_ctrl_info *ctrl = &adapter->ctrl; | 1515 | struct be_ctrl_info *ctrl = &adapter->ctrl; |
| 1496 | struct be_eq_obj *rx_eq = &adapter->rx_eq; | 1516 | struct be_eq_obj *rx_eq = &adapter->rx_eq; |
| 1497 | struct be_eq_obj *tx_eq = &adapter->tx_eq; | 1517 | struct be_eq_obj *tx_eq = &adapter->tx_eq; |
| 1518 | bool link_up; | ||
| 1519 | int status; | ||
| 1520 | |||
| 1521 | /* First time posting */ | ||
| 1522 | be_post_rx_frags(adapter); | ||
| 1523 | |||
| 1524 | napi_enable(&rx_eq->napi); | ||
| 1525 | napi_enable(&tx_eq->napi); | ||
| 1526 | |||
| 1527 | be_irq_register(adapter); | ||
| 1528 | |||
| 1529 | be_intr_set(ctrl, true); | ||
| 1530 | |||
| 1531 | /* The evt queues are created in unarmed state; arm them */ | ||
| 1532 | be_eq_notify(ctrl, rx_eq->q.id, true, false, 0); | ||
| 1533 | be_eq_notify(ctrl, tx_eq->q.id, true, false, 0); | ||
| 1534 | |||
| 1535 | /* Rx compl queue may be in unarmed state; rearm it */ | ||
| 1536 | be_cq_notify(ctrl, adapter->rx_obj.cq.id, true, 0); | ||
| 1537 | |||
| 1538 | status = be_cmd_link_status_query(ctrl, &link_up); | ||
| 1539 | if (status) | ||
| 1540 | return status; | ||
| 1541 | be_link_status_update(adapter, link_up); | ||
| 1542 | |||
| 1543 | schedule_delayed_work(&adapter->work, msecs_to_jiffies(100)); | ||
| 1544 | return 0; | ||
| 1545 | } | ||
| 1546 | |||
| 1547 | static int be_setup(struct be_adapter *adapter) | ||
| 1548 | { | ||
| 1549 | struct be_ctrl_info *ctrl = &adapter->ctrl; | ||
| 1550 | struct net_device *netdev = adapter->netdev; | ||
| 1498 | u32 if_flags; | 1551 | u32 if_flags; |
| 1499 | int status; | 1552 | int status; |
| 1500 | 1553 | ||
| @@ -1521,29 +1574,14 @@ static int be_open(struct net_device *netdev) | |||
| 1521 | if (status != 0) | 1574 | if (status != 0) |
| 1522 | goto tx_qs_destroy; | 1575 | goto tx_qs_destroy; |
| 1523 | 1576 | ||
| 1524 | /* First time posting */ | 1577 | status = be_mcc_queues_create(adapter); |
| 1525 | be_post_rx_frags(adapter); | 1578 | if (status != 0) |
| 1526 | 1579 | goto rx_qs_destroy; | |
| 1527 | napi_enable(&rx_eq->napi); | ||
| 1528 | napi_enable(&tx_eq->napi); | ||
| 1529 | |||
| 1530 | be_irq_register(adapter); | ||
| 1531 | |||
| 1532 | be_intr_set(ctrl, true); | ||
| 1533 | |||
| 1534 | /* The evt queues are created in the unarmed state; arm them */ | ||
| 1535 | be_eq_notify(ctrl, rx_eq->q.id, true, false, 0); | ||
| 1536 | be_eq_notify(ctrl, tx_eq->q.id, true, false, 0); | ||
| 1537 | |||
| 1538 | /* The compl queues are created in the unarmed state; arm them */ | ||
| 1539 | be_cq_notify(ctrl, adapter->rx_obj.cq.id, true, 0); | ||
| 1540 | be_cq_notify(ctrl, adapter->tx_obj.cq.id, true, 0); | ||
| 1541 | |||
| 1542 | be_link_status_update(adapter); | ||
| 1543 | 1580 | ||
| 1544 | schedule_delayed_work(&adapter->work, msecs_to_jiffies(100)); | ||
| 1545 | return 0; | 1581 | return 0; |
| 1546 | 1582 | ||
| 1583 | rx_qs_destroy: | ||
| 1584 | be_rx_queues_destroy(adapter); | ||
| 1547 | tx_qs_destroy: | 1585 | tx_qs_destroy: |
| 1548 | be_tx_queues_destroy(adapter); | 1586 | be_tx_queues_destroy(adapter); |
| 1549 | if_destroy: | 1587 | if_destroy: |
| @@ -1552,6 +1590,19 @@ do_none: | |||
| 1552 | return status; | 1590 | return status; |
| 1553 | } | 1591 | } |
| 1554 | 1592 | ||
| 1593 | static int be_clear(struct be_adapter *adapter) | ||
| 1594 | { | ||
| 1595 | struct be_ctrl_info *ctrl = &adapter->ctrl; | ||
| 1596 | |||
| 1597 | be_rx_queues_destroy(adapter); | ||
| 1598 | be_tx_queues_destroy(adapter); | ||
| 1599 | |||
| 1600 | be_cmd_if_destroy(ctrl, adapter->if_handle); | ||
| 1601 | |||
| 1602 | be_mcc_queues_destroy(adapter); | ||
| 1603 | return 0; | ||
| 1604 | } | ||
| 1605 | |||
| 1555 | static int be_close(struct net_device *netdev) | 1606 | static int be_close(struct net_device *netdev) |
| 1556 | { | 1607 | { |
| 1557 | struct be_adapter *adapter = netdev_priv(netdev); | 1608 | struct be_adapter *adapter = netdev_priv(netdev); |
| @@ -1564,7 +1615,7 @@ static int be_close(struct net_device *netdev) | |||
| 1564 | 1615 | ||
| 1565 | netif_stop_queue(netdev); | 1616 | netif_stop_queue(netdev); |
| 1566 | netif_carrier_off(netdev); | 1617 | netif_carrier_off(netdev); |
| 1567 | adapter->link.speed = PHY_LINK_SPEED_ZERO; | 1618 | adapter->link_up = false; |
| 1568 | 1619 | ||
| 1569 | be_intr_set(ctrl, false); | 1620 | be_intr_set(ctrl, false); |
| 1570 | 1621 | ||
| @@ -1581,10 +1632,6 @@ static int be_close(struct net_device *netdev) | |||
| 1581 | napi_disable(&rx_eq->napi); | 1632 | napi_disable(&rx_eq->napi); |
| 1582 | napi_disable(&tx_eq->napi); | 1633 | napi_disable(&tx_eq->napi); |
| 1583 | 1634 | ||
| 1584 | be_rx_queues_destroy(adapter); | ||
| 1585 | be_tx_queues_destroy(adapter); | ||
| 1586 | |||
| 1587 | be_cmd_if_destroy(ctrl, adapter->if_handle); | ||
| 1588 | return 0; | 1635 | return 0; |
| 1589 | } | 1636 | } |
| 1590 | 1637 | ||
| @@ -1673,7 +1720,7 @@ static void be_netdev_init(struct net_device *netdev) | |||
| 1673 | 1720 | ||
| 1674 | netif_napi_add(netdev, &adapter->rx_eq.napi, be_poll_rx, | 1721 | netif_napi_add(netdev, &adapter->rx_eq.napi, be_poll_rx, |
| 1675 | BE_NAPI_WEIGHT); | 1722 | BE_NAPI_WEIGHT); |
| 1676 | netif_napi_add(netdev, &adapter->tx_eq.napi, be_poll_tx, | 1723 | netif_napi_add(netdev, &adapter->tx_eq.napi, be_poll_tx_mcc, |
| 1677 | BE_NAPI_WEIGHT); | 1724 | BE_NAPI_WEIGHT); |
| 1678 | 1725 | ||
| 1679 | netif_carrier_off(netdev); | 1726 | netif_carrier_off(netdev); |
| @@ -1755,7 +1802,12 @@ static int be_ctrl_init(struct be_adapter *adapter) | |||
| 1755 | mbox_mem_align->va = PTR_ALIGN(mbox_mem_alloc->va, 16); | 1802 | mbox_mem_align->va = PTR_ALIGN(mbox_mem_alloc->va, 16); |
| 1756 | mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16); | 1803 | mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16); |
| 1757 | memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox)); | 1804 | memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox)); |
| 1758 | spin_lock_init(&ctrl->cmd_lock); | 1805 | spin_lock_init(&ctrl->mbox_lock); |
| 1806 | spin_lock_init(&ctrl->mcc_lock); | ||
| 1807 | spin_lock_init(&ctrl->mcc_cq_lock); | ||
| 1808 | |||
| 1809 | ctrl->async_cb = be_link_status_update; | ||
| 1810 | ctrl->adapter_ctxt = adapter; | ||
| 1759 | 1811 | ||
| 1760 | val = ioread32(ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET); | 1812 | val = ioread32(ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET); |
| 1761 | ctrl->pci_func = (val >> MEMBAR_CTRL_INT_CTRL_PFUNC_SHIFT) & | 1813 | ctrl->pci_func = (val >> MEMBAR_CTRL_INT_CTRL_PFUNC_SHIFT) & |
| @@ -1793,6 +1845,8 @@ static void __devexit be_remove(struct pci_dev *pdev) | |||
| 1793 | 1845 | ||
| 1794 | unregister_netdev(adapter->netdev); | 1846 | unregister_netdev(adapter->netdev); |
| 1795 | 1847 | ||
| 1848 | be_clear(adapter); | ||
| 1849 | |||
| 1796 | be_stats_cleanup(adapter); | 1850 | be_stats_cleanup(adapter); |
| 1797 | 1851 | ||
| 1798 | be_ctrl_cleanup(adapter); | 1852 | be_ctrl_cleanup(adapter); |
| @@ -1890,13 +1944,18 @@ static int __devinit be_probe(struct pci_dev *pdev, | |||
| 1890 | be_netdev_init(netdev); | 1944 | be_netdev_init(netdev); |
| 1891 | SET_NETDEV_DEV(netdev, &adapter->pdev->dev); | 1945 | SET_NETDEV_DEV(netdev, &adapter->pdev->dev); |
| 1892 | 1946 | ||
| 1947 | status = be_setup(adapter); | ||
| 1948 | if (status) | ||
| 1949 | goto stats_clean; | ||
| 1893 | status = register_netdev(netdev); | 1950 | status = register_netdev(netdev); |
| 1894 | if (status != 0) | 1951 | if (status != 0) |
| 1895 | goto stats_clean; | 1952 | goto unsetup; |
| 1896 | 1953 | ||
| 1897 | dev_info(&pdev->dev, "%s port %d\n", nic_name(pdev), adapter->port_num); | 1954 | dev_info(&pdev->dev, "%s port %d\n", nic_name(pdev), adapter->port_num); |
| 1898 | return 0; | 1955 | return 0; |
| 1899 | 1956 | ||
| 1957 | unsetup: | ||
| 1958 | be_clear(adapter); | ||
| 1900 | stats_clean: | 1959 | stats_clean: |
| 1901 | be_stats_cleanup(adapter); | 1960 | be_stats_cleanup(adapter); |
| 1902 | ctrl_clean: | 1961 | ctrl_clean: |
| @@ -1921,6 +1980,7 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state) | |||
| 1921 | if (netif_running(netdev)) { | 1980 | if (netif_running(netdev)) { |
| 1922 | rtnl_lock(); | 1981 | rtnl_lock(); |
| 1923 | be_close(netdev); | 1982 | be_close(netdev); |
| 1983 | be_clear(adapter); | ||
| 1924 | rtnl_unlock(); | 1984 | rtnl_unlock(); |
| 1925 | } | 1985 | } |
| 1926 | 1986 | ||
| @@ -1947,6 +2007,7 @@ static int be_resume(struct pci_dev *pdev) | |||
| 1947 | 2007 | ||
| 1948 | if (netif_running(netdev)) { | 2008 | if (netif_running(netdev)) { |
| 1949 | rtnl_lock(); | 2009 | rtnl_lock(); |
| 2010 | be_setup(adapter); | ||
| 1950 | be_open(netdev); | 2011 | be_open(netdev); |
| 1951 | rtnl_unlock(); | 2012 | rtnl_unlock(); |
| 1952 | } | 2013 | } |
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 677f60490f67..679885a122b4 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c | |||
| @@ -1997,7 +1997,7 @@ static int e1000_clean(struct napi_struct *napi, int budget) | |||
| 1997 | struct e1000_adapter *adapter = container_of(napi, struct e1000_adapter, napi); | 1997 | struct e1000_adapter *adapter = container_of(napi, struct e1000_adapter, napi); |
| 1998 | struct e1000_hw *hw = &adapter->hw; | 1998 | struct e1000_hw *hw = &adapter->hw; |
| 1999 | struct net_device *poll_dev = adapter->netdev; | 1999 | struct net_device *poll_dev = adapter->netdev; |
| 2000 | int tx_cleaned = 0, work_done = 0; | 2000 | int tx_cleaned = 1, work_done = 0; |
| 2001 | 2001 | ||
| 2002 | adapter = netdev_priv(poll_dev); | 2002 | adapter = netdev_priv(poll_dev); |
| 2003 | 2003 | ||
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c index e02bafdd3682..93f4abd990a9 100644 --- a/drivers/net/mlx4/en_netdev.c +++ b/drivers/net/mlx4/en_netdev.c | |||
| @@ -668,7 +668,7 @@ int mlx4_en_start_port(struct net_device *dev) | |||
| 668 | queue_work(mdev->workqueue, &priv->mcast_task); | 668 | queue_work(mdev->workqueue, &priv->mcast_task); |
| 669 | 669 | ||
| 670 | priv->port_up = true; | 670 | priv->port_up = true; |
| 671 | netif_start_queue(dev); | 671 | netif_tx_start_all_queues(dev); |
| 672 | return 0; | 672 | return 0; |
| 673 | 673 | ||
| 674 | mac_err: | 674 | mac_err: |
| @@ -700,14 +700,14 @@ void mlx4_en_stop_port(struct net_device *dev) | |||
| 700 | en_dbg(DRV, priv, "stop port called while port already down\n"); | 700 | en_dbg(DRV, priv, "stop port called while port already down\n"); |
| 701 | return; | 701 | return; |
| 702 | } | 702 | } |
| 703 | netif_stop_queue(dev); | ||
| 704 | 703 | ||
| 705 | /* Synchronize with tx routine */ | 704 | /* Synchronize with tx routine */ |
| 706 | netif_tx_lock_bh(dev); | 705 | netif_tx_lock_bh(dev); |
| 707 | priv->port_up = false; | 706 | netif_tx_stop_all_queues(dev); |
| 708 | netif_tx_unlock_bh(dev); | 707 | netif_tx_unlock_bh(dev); |
| 709 | 708 | ||
| 710 | /* close port*/ | 709 | /* close port*/ |
| 710 | priv->port_up = false; | ||
| 711 | mlx4_CLOSE_PORT(mdev->dev, priv->port); | 711 | mlx4_CLOSE_PORT(mdev->dev, priv->port); |
| 712 | 712 | ||
| 713 | /* Unregister Mac address for the port */ | 713 | /* Unregister Mac address for the port */ |
| @@ -881,7 +881,6 @@ void mlx4_en_destroy_netdev(struct net_device *dev) | |||
| 881 | mlx4_free_hwq_res(mdev->dev, &priv->res, MLX4_EN_PAGE_SIZE); | 881 | mlx4_free_hwq_res(mdev->dev, &priv->res, MLX4_EN_PAGE_SIZE); |
| 882 | 882 | ||
| 883 | cancel_delayed_work(&priv->stats_task); | 883 | cancel_delayed_work(&priv->stats_task); |
| 884 | cancel_delayed_work(&priv->refill_task); | ||
| 885 | /* flush any pending task for this netdev */ | 884 | /* flush any pending task for this netdev */ |
| 886 | flush_workqueue(mdev->workqueue); | 885 | flush_workqueue(mdev->workqueue); |
| 887 | 886 | ||
| @@ -986,7 +985,6 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, | |||
| 986 | spin_lock_init(&priv->stats_lock); | 985 | spin_lock_init(&priv->stats_lock); |
| 987 | INIT_WORK(&priv->mcast_task, mlx4_en_do_set_multicast); | 986 | INIT_WORK(&priv->mcast_task, mlx4_en_do_set_multicast); |
| 988 | INIT_WORK(&priv->mac_task, mlx4_en_do_set_mac); | 987 | INIT_WORK(&priv->mac_task, mlx4_en_do_set_mac); |
| 989 | INIT_DELAYED_WORK(&priv->refill_task, mlx4_en_rx_refill); | ||
| 990 | INIT_WORK(&priv->watchdog_task, mlx4_en_restart); | 988 | INIT_WORK(&priv->watchdog_task, mlx4_en_restart); |
| 991 | INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate); | 989 | INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate); |
| 992 | INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats); | 990 | INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats); |
diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c index 5a14899c1e25..91bdfdfd431f 100644 --- a/drivers/net/mlx4/en_rx.c +++ b/drivers/net/mlx4/en_rx.c | |||
| @@ -269,31 +269,6 @@ reduce_rings: | |||
| 269 | return 0; | 269 | return 0; |
| 270 | } | 270 | } |
| 271 | 271 | ||
| 272 | static int mlx4_en_fill_rx_buf(struct net_device *dev, | ||
| 273 | struct mlx4_en_rx_ring *ring) | ||
| 274 | { | ||
| 275 | struct mlx4_en_priv *priv = netdev_priv(dev); | ||
| 276 | int num = 0; | ||
| 277 | int err; | ||
| 278 | |||
| 279 | while ((u32) (ring->prod - ring->cons) < ring->actual_size) { | ||
| 280 | err = mlx4_en_prepare_rx_desc(priv, ring, ring->prod & | ||
| 281 | ring->size_mask); | ||
| 282 | if (err) { | ||
| 283 | if (netif_msg_rx_err(priv)) | ||
| 284 | en_warn(priv, "Failed preparing rx descriptor\n"); | ||
| 285 | priv->port_stats.rx_alloc_failed++; | ||
| 286 | break; | ||
| 287 | } | ||
| 288 | ++num; | ||
| 289 | ++ring->prod; | ||
| 290 | } | ||
| 291 | if ((u32) (ring->prod - ring->cons) == ring->actual_size) | ||
| 292 | ring->full = 1; | ||
| 293 | |||
| 294 | return num; | ||
| 295 | } | ||
| 296 | |||
| 297 | static void mlx4_en_free_rx_buf(struct mlx4_en_priv *priv, | 272 | static void mlx4_en_free_rx_buf(struct mlx4_en_priv *priv, |
| 298 | struct mlx4_en_rx_ring *ring) | 273 | struct mlx4_en_rx_ring *ring) |
| 299 | { | 274 | { |
| @@ -312,42 +287,6 @@ static void mlx4_en_free_rx_buf(struct mlx4_en_priv *priv, | |||
| 312 | } | 287 | } |
| 313 | } | 288 | } |
| 314 | 289 | ||
| 315 | |||
| 316 | void mlx4_en_rx_refill(struct work_struct *work) | ||
| 317 | { | ||
| 318 | struct delayed_work *delay = to_delayed_work(work); | ||
| 319 | struct mlx4_en_priv *priv = container_of(delay, struct mlx4_en_priv, | ||
| 320 | refill_task); | ||
| 321 | struct mlx4_en_dev *mdev = priv->mdev; | ||
| 322 | struct net_device *dev = priv->dev; | ||
| 323 | struct mlx4_en_rx_ring *ring; | ||
| 324 | int need_refill = 0; | ||
| 325 | int i; | ||
| 326 | |||
| 327 | mutex_lock(&mdev->state_lock); | ||
| 328 | if (!mdev->device_up || !priv->port_up) | ||
| 329 | goto out; | ||
| 330 | |||
| 331 | /* We only get here if there are no receive buffers, so we can't race | ||
| 332 | * with Rx interrupts while filling buffers */ | ||
| 333 | for (i = 0; i < priv->rx_ring_num; i++) { | ||
| 334 | ring = &priv->rx_ring[i]; | ||
| 335 | if (ring->need_refill) { | ||
| 336 | if (mlx4_en_fill_rx_buf(dev, ring)) { | ||
| 337 | ring->need_refill = 0; | ||
| 338 | mlx4_en_update_rx_prod_db(ring); | ||
| 339 | } else | ||
| 340 | need_refill = 1; | ||
| 341 | } | ||
| 342 | } | ||
| 343 | if (need_refill) | ||
| 344 | queue_delayed_work(mdev->workqueue, &priv->refill_task, HZ); | ||
| 345 | |||
| 346 | out: | ||
| 347 | mutex_unlock(&mdev->state_lock); | ||
| 348 | } | ||
| 349 | |||
| 350 | |||
| 351 | int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv, | 290 | int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv, |
| 352 | struct mlx4_en_rx_ring *ring, u32 size, u16 stride) | 291 | struct mlx4_en_rx_ring *ring, u32 size, u16 stride) |
| 353 | { | 292 | { |
| @@ -457,9 +396,6 @@ int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv) | |||
| 457 | ring_ind--; | 396 | ring_ind--; |
| 458 | goto err_allocator; | 397 | goto err_allocator; |
| 459 | } | 398 | } |
| 460 | |||
| 461 | /* Fill Rx buffers */ | ||
| 462 | ring->full = 0; | ||
| 463 | } | 399 | } |
| 464 | err = mlx4_en_fill_rx_buffers(priv); | 400 | err = mlx4_en_fill_rx_buffers(priv); |
| 465 | if (err) | 401 | if (err) |
| @@ -647,33 +583,6 @@ static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv, | |||
| 647 | return skb; | 583 | return skb; |
| 648 | } | 584 | } |
| 649 | 585 | ||
| 650 | static void mlx4_en_copy_desc(struct mlx4_en_priv *priv, | ||
| 651 | struct mlx4_en_rx_ring *ring, | ||
| 652 | int from, int to, int num) | ||
| 653 | { | ||
| 654 | struct skb_frag_struct *skb_frags_from; | ||
| 655 | struct skb_frag_struct *skb_frags_to; | ||
| 656 | struct mlx4_en_rx_desc *rx_desc_from; | ||
| 657 | struct mlx4_en_rx_desc *rx_desc_to; | ||
| 658 | int from_index, to_index; | ||
| 659 | int nr, i; | ||
| 660 | |||
| 661 | for (i = 0; i < num; i++) { | ||
| 662 | from_index = (from + i) & ring->size_mask; | ||
| 663 | to_index = (to + i) & ring->size_mask; | ||
| 664 | skb_frags_from = ring->rx_info + (from_index << priv->log_rx_info); | ||
| 665 | skb_frags_to = ring->rx_info + (to_index << priv->log_rx_info); | ||
| 666 | rx_desc_from = ring->buf + (from_index << ring->log_stride); | ||
| 667 | rx_desc_to = ring->buf + (to_index << ring->log_stride); | ||
| 668 | |||
| 669 | for (nr = 0; nr < priv->num_frags; nr++) { | ||
| 670 | skb_frags_to[nr].page = skb_frags_from[nr].page; | ||
| 671 | skb_frags_to[nr].page_offset = skb_frags_from[nr].page_offset; | ||
| 672 | rx_desc_to->data[nr].addr = rx_desc_from->data[nr].addr; | ||
| 673 | } | ||
| 674 | } | ||
| 675 | } | ||
| 676 | |||
| 677 | 586 | ||
| 678 | int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int budget) | 587 | int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int budget) |
| 679 | { | 588 | { |
| @@ -821,11 +730,6 @@ out: | |||
| 821 | wmb(); /* ensure HW sees CQ consumer before we post new buffers */ | 730 | wmb(); /* ensure HW sees CQ consumer before we post new buffers */ |
| 822 | ring->cons = cq->mcq.cons_index; | 731 | ring->cons = cq->mcq.cons_index; |
| 823 | ring->prod += polled; /* Polled descriptors were realocated in place */ | 732 | ring->prod += polled; /* Polled descriptors were realocated in place */ |
| 824 | if (unlikely(!ring->full)) { | ||
| 825 | mlx4_en_copy_desc(priv, ring, ring->cons - polled, | ||
| 826 | ring->prod - polled, polled); | ||
| 827 | mlx4_en_fill_rx_buf(dev, ring); | ||
| 828 | } | ||
| 829 | mlx4_en_update_rx_prod_db(ring); | 733 | mlx4_en_update_rx_prod_db(ring); |
| 830 | return polled; | 734 | return polled; |
| 831 | } | 735 | } |
diff --git a/drivers/net/mlx4/en_tx.c b/drivers/net/mlx4/en_tx.c index 5dc7466ad035..08c43f2ae72b 100644 --- a/drivers/net/mlx4/en_tx.c +++ b/drivers/net/mlx4/en_tx.c | |||
| @@ -515,16 +515,9 @@ static int get_real_size(struct sk_buff *skb, struct net_device *dev, | |||
| 515 | else { | 515 | else { |
| 516 | if (netif_msg_tx_err(priv)) | 516 | if (netif_msg_tx_err(priv)) |
| 517 | en_warn(priv, "Non-linear headers\n"); | 517 | en_warn(priv, "Non-linear headers\n"); |
| 518 | dev_kfree_skb_any(skb); | ||
| 519 | return 0; | 518 | return 0; |
| 520 | } | 519 | } |
| 521 | } | 520 | } |
| 522 | if (unlikely(*lso_header_size > MAX_LSO_HDR_SIZE)) { | ||
| 523 | if (netif_msg_tx_err(priv)) | ||
| 524 | en_warn(priv, "LSO header size too big\n"); | ||
| 525 | dev_kfree_skb_any(skb); | ||
| 526 | return 0; | ||
| 527 | } | ||
| 528 | } else { | 521 | } else { |
| 529 | *lso_header_size = 0; | 522 | *lso_header_size = 0; |
| 530 | if (!is_inline(skb, NULL)) | 523 | if (!is_inline(skb, NULL)) |
| @@ -616,13 +609,9 @@ int mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 616 | int lso_header_size; | 609 | int lso_header_size; |
| 617 | void *fragptr; | 610 | void *fragptr; |
| 618 | 611 | ||
| 619 | if (unlikely(!skb->len)) { | ||
| 620 | dev_kfree_skb_any(skb); | ||
| 621 | return NETDEV_TX_OK; | ||
| 622 | } | ||
| 623 | real_size = get_real_size(skb, dev, &lso_header_size); | 612 | real_size = get_real_size(skb, dev, &lso_header_size); |
| 624 | if (unlikely(!real_size)) | 613 | if (unlikely(!real_size)) |
| 625 | return NETDEV_TX_OK; | 614 | goto tx_drop; |
| 626 | 615 | ||
| 627 | /* Allign descriptor to TXBB size */ | 616 | /* Allign descriptor to TXBB size */ |
| 628 | desc_size = ALIGN(real_size, TXBB_SIZE); | 617 | desc_size = ALIGN(real_size, TXBB_SIZE); |
| @@ -630,8 +619,7 @@ int mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 630 | if (unlikely(nr_txbb > MAX_DESC_TXBBS)) { | 619 | if (unlikely(nr_txbb > MAX_DESC_TXBBS)) { |
| 631 | if (netif_msg_tx_err(priv)) | 620 | if (netif_msg_tx_err(priv)) |
| 632 | en_warn(priv, "Oversized header or SG list\n"); | 621 | en_warn(priv, "Oversized header or SG list\n"); |
| 633 | dev_kfree_skb_any(skb); | 622 | goto tx_drop; |
| 634 | return NETDEV_TX_OK; | ||
| 635 | } | 623 | } |
| 636 | 624 | ||
| 637 | tx_ind = skb->queue_mapping; | 625 | tx_ind = skb->queue_mapping; |
| @@ -653,14 +641,6 @@ int mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 653 | return NETDEV_TX_BUSY; | 641 | return NETDEV_TX_BUSY; |
| 654 | } | 642 | } |
| 655 | 643 | ||
| 656 | /* Now that we know what Tx ring to use */ | ||
| 657 | if (unlikely(!priv->port_up)) { | ||
| 658 | if (netif_msg_tx_err(priv)) | ||
| 659 | en_warn(priv, "xmit: port down!\n"); | ||
| 660 | dev_kfree_skb_any(skb); | ||
| 661 | return NETDEV_TX_OK; | ||
| 662 | } | ||
| 663 | |||
| 664 | /* Track current inflight packets for performance analysis */ | 644 | /* Track current inflight packets for performance analysis */ |
| 665 | AVG_PERF_COUNTER(priv->pstats.inflight_avg, | 645 | AVG_PERF_COUNTER(priv->pstats.inflight_avg, |
| 666 | (u32) (ring->prod - ring->cons - 1)); | 646 | (u32) (ring->prod - ring->cons - 1)); |
| @@ -785,5 +765,10 @@ int mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 785 | mlx4_en_xmit_poll(priv, tx_ind); | 765 | mlx4_en_xmit_poll(priv, tx_ind); |
| 786 | 766 | ||
| 787 | return 0; | 767 | return 0; |
| 768 | |||
| 769 | tx_drop: | ||
| 770 | dev_kfree_skb_any(skb); | ||
| 771 | priv->stats.tx_dropped++; | ||
| 772 | return NETDEV_TX_OK; | ||
| 788 | } | 773 | } |
| 789 | 774 | ||
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h index d43a9e4c2aea..c7c5e86804ff 100644 --- a/drivers/net/mlx4/mlx4_en.h +++ b/drivers/net/mlx4/mlx4_en.h | |||
| @@ -99,7 +99,6 @@ | |||
| 99 | #define RSS_FACTOR 2 | 99 | #define RSS_FACTOR 2 |
| 100 | #define TXBB_SIZE 64 | 100 | #define TXBB_SIZE 64 |
| 101 | #define HEADROOM (2048 / TXBB_SIZE + 1) | 101 | #define HEADROOM (2048 / TXBB_SIZE + 1) |
| 102 | #define MAX_LSO_HDR_SIZE 92 | ||
| 103 | #define STAMP_STRIDE 64 | 102 | #define STAMP_STRIDE 64 |
| 104 | #define STAMP_DWORDS (STAMP_STRIDE / 4) | 103 | #define STAMP_DWORDS (STAMP_STRIDE / 4) |
| 105 | #define STAMP_SHIFT 31 | 104 | #define STAMP_SHIFT 31 |
| @@ -296,8 +295,6 @@ struct mlx4_en_rx_ring { | |||
| 296 | u32 prod; | 295 | u32 prod; |
| 297 | u32 cons; | 296 | u32 cons; |
| 298 | u32 buf_size; | 297 | u32 buf_size; |
| 299 | int need_refill; | ||
| 300 | int full; | ||
| 301 | void *buf; | 298 | void *buf; |
| 302 | void *rx_info; | 299 | void *rx_info; |
| 303 | unsigned long bytes; | 300 | unsigned long bytes; |
| @@ -495,7 +492,6 @@ struct mlx4_en_priv { | |||
| 495 | struct mlx4_en_cq rx_cq[MAX_RX_RINGS]; | 492 | struct mlx4_en_cq rx_cq[MAX_RX_RINGS]; |
| 496 | struct work_struct mcast_task; | 493 | struct work_struct mcast_task; |
| 497 | struct work_struct mac_task; | 494 | struct work_struct mac_task; |
| 498 | struct delayed_work refill_task; | ||
| 499 | struct work_struct watchdog_task; | 495 | struct work_struct watchdog_task; |
| 500 | struct work_struct linkstate_task; | 496 | struct work_struct linkstate_task; |
| 501 | struct delayed_work stats_task; | 497 | struct delayed_work stats_task; |
| @@ -565,7 +561,6 @@ void mlx4_en_set_default_rss_map(struct mlx4_en_priv *priv, | |||
| 565 | int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv); | 561 | int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv); |
| 566 | void mlx4_en_release_rss_steer(struct mlx4_en_priv *priv); | 562 | void mlx4_en_release_rss_steer(struct mlx4_en_priv *priv); |
| 567 | int mlx4_en_free_tx_buf(struct net_device *dev, struct mlx4_en_tx_ring *ring); | 563 | int mlx4_en_free_tx_buf(struct net_device *dev, struct mlx4_en_tx_ring *ring); |
| 568 | void mlx4_en_rx_refill(struct work_struct *work); | ||
| 569 | void mlx4_en_rx_irq(struct mlx4_cq *mcq); | 564 | void mlx4_en_rx_irq(struct mlx4_cq *mcq); |
| 570 | 565 | ||
| 571 | int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, u64 mac, u64 clear, u8 mode); | 566 | int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, u64 mac, u64 clear, u8 mode); |
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 745ae8b4a2e8..0f32db3e92ad 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c | |||
| @@ -1750,12 +1750,12 @@ static void mv643xx_eth_program_unicast_filter(struct net_device *dev) | |||
| 1750 | 1750 | ||
| 1751 | uc_addr_set(mp, dev->dev_addr); | 1751 | uc_addr_set(mp, dev->dev_addr); |
| 1752 | 1752 | ||
| 1753 | port_config = rdlp(mp, PORT_CONFIG); | 1753 | port_config = rdlp(mp, PORT_CONFIG) & ~UNICAST_PROMISCUOUS_MODE; |
| 1754 | |||
| 1754 | nibbles = uc_addr_filter_mask(dev); | 1755 | nibbles = uc_addr_filter_mask(dev); |
| 1755 | if (!nibbles) { | 1756 | if (!nibbles) { |
| 1756 | port_config |= UNICAST_PROMISCUOUS_MODE; | 1757 | port_config |= UNICAST_PROMISCUOUS_MODE; |
| 1757 | wrlp(mp, PORT_CONFIG, port_config); | 1758 | nibbles = 0xffff; |
| 1758 | return; | ||
| 1759 | } | 1759 | } |
| 1760 | 1760 | ||
| 1761 | for (i = 0; i < 16; i += 4) { | 1761 | for (i = 0; i < 16; i += 4) { |
| @@ -1776,7 +1776,6 @@ static void mv643xx_eth_program_unicast_filter(struct net_device *dev) | |||
| 1776 | wrl(mp, off, v); | 1776 | wrl(mp, off, v); |
| 1777 | } | 1777 | } |
| 1778 | 1778 | ||
| 1779 | port_config &= ~UNICAST_PROMISCUOUS_MODE; | ||
| 1780 | wrlp(mp, PORT_CONFIG, port_config); | 1779 | wrlp(mp, PORT_CONFIG, port_config); |
| 1781 | } | 1780 | } |
| 1782 | 1781 | ||
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index 8a823ecc99a9..bbc6d4d3cc94 100644 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c | |||
| @@ -3837,7 +3837,9 @@ static void ql_reset_work(struct work_struct *work) | |||
| 3837 | 16) | ISP_CONTROL_RI)); | 3837 | 16) | ISP_CONTROL_RI)); |
| 3838 | } | 3838 | } |
| 3839 | 3839 | ||
| 3840 | spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); | ||
| 3840 | ssleep(1); | 3841 | ssleep(1); |
| 3842 | spin_lock_irqsave(&qdev->hw_lock, hw_flags); | ||
| 3841 | } while (--max_wait_time); | 3843 | } while (--max_wait_time); |
| 3842 | spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); | 3844 | spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); |
| 3843 | 3845 | ||
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 4e22462684c9..4b53b58d75fc 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c | |||
| @@ -51,9 +51,6 @@ | |||
| 51 | #define TX_BUFFS_AVAIL(tp) \ | 51 | #define TX_BUFFS_AVAIL(tp) \ |
| 52 | (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1) | 52 | (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1) |
| 53 | 53 | ||
| 54 | /* Maximum events (Rx packets, etc.) to handle at each interrupt. */ | ||
| 55 | static const int max_interrupt_work = 20; | ||
| 56 | |||
| 57 | /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). | 54 | /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). |
| 58 | The RTL chips use a 64 element hash table based on the Ethernet CRC. */ | 55 | The RTL chips use a 64 element hash table based on the Ethernet CRC. */ |
| 59 | static const int multicast_filter_limit = 32; | 56 | static const int multicast_filter_limit = 32; |
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 3717569828bf..a906d3998131 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig | |||
| @@ -169,10 +169,12 @@ config USB_NET_CDCETHER | |||
| 169 | The Linux-USB CDC Ethernet Gadget driver is an open implementation. | 169 | The Linux-USB CDC Ethernet Gadget driver is an open implementation. |
| 170 | This driver should work with at least the following devices: | 170 | This driver should work with at least the following devices: |
| 171 | 171 | ||
| 172 | * Dell Wireless 5530 HSPA | ||
| 172 | * Ericsson PipeRider (all variants) | 173 | * Ericsson PipeRider (all variants) |
| 174 | * Ericsson Mobile Broadband Module (all variants) | ||
| 173 | * Motorola (DM100 and SB4100) | 175 | * Motorola (DM100 and SB4100) |
| 174 | * Broadcom Cable Modem (reference design) | 176 | * Broadcom Cable Modem (reference design) |
| 175 | * Toshiba PCX1100U | 177 | * Toshiba (PCX1100U and F3507g) |
| 176 | * ... | 178 | * ... |
| 177 | 179 | ||
| 178 | This driver creates an interface named "ethX", where X depends on | 180 | This driver creates an interface named "ethX", where X depends on |
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 01fd528306ec..4a6aff579403 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c | |||
| @@ -533,6 +533,31 @@ static const struct usb_device_id products [] = { | |||
| 533 | USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1900, USB_CLASS_COMM, | 533 | USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1900, USB_CLASS_COMM, |
| 534 | USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), | 534 | USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), |
| 535 | .driver_info = (unsigned long) &cdc_info, | 535 | .driver_info = (unsigned long) &cdc_info, |
| 536 | }, { | ||
| 537 | /* Ericsson F3507g ver. 2 */ | ||
| 538 | USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1902, USB_CLASS_COMM, | ||
| 539 | USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), | ||
| 540 | .driver_info = (unsigned long) &cdc_info, | ||
| 541 | }, { | ||
| 542 | /* Ericsson F3607gw */ | ||
| 543 | USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1904, USB_CLASS_COMM, | ||
| 544 | USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), | ||
| 545 | .driver_info = (unsigned long) &cdc_info, | ||
| 546 | }, { | ||
| 547 | /* Ericsson F3307 */ | ||
| 548 | USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1906, USB_CLASS_COMM, | ||
| 549 | USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), | ||
| 550 | .driver_info = (unsigned long) &cdc_info, | ||
| 551 | }, { | ||
| 552 | /* Toshiba F3507g */ | ||
| 553 | USB_DEVICE_AND_INTERFACE_INFO(0x0930, 0x130b, USB_CLASS_COMM, | ||
| 554 | USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), | ||
| 555 | .driver_info = (unsigned long) &cdc_info, | ||
| 556 | }, { | ||
| 557 | /* Dell F3507g */ | ||
| 558 | USB_DEVICE_AND_INTERFACE_INFO(0x413c, 0x8147, USB_CLASS_COMM, | ||
| 559 | USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), | ||
| 560 | .driver_info = (unsigned long) &cdc_info, | ||
| 536 | }, | 561 | }, |
| 537 | { }, // END | 562 | { }, // END |
| 538 | }; | 563 | }; |
diff --git a/drivers/net/usb/cdc_subset.c b/drivers/net/usb/cdc_subset.c index c66b9c324f54..ca39ace0b0eb 100644 --- a/drivers/net/usb/cdc_subset.c +++ b/drivers/net/usb/cdc_subset.c | |||
| @@ -307,9 +307,10 @@ static const struct usb_device_id products [] = { | |||
| 307 | USB_DEVICE (0x1286, 0x8001), // "blob" bootloader | 307 | USB_DEVICE (0x1286, 0x8001), // "blob" bootloader |
| 308 | .driver_info = (unsigned long) &blob_info, | 308 | .driver_info = (unsigned long) &blob_info, |
| 309 | }, { | 309 | }, { |
| 310 | // Linux Ethernet/RNDIS gadget on pxa210/25x/26x, second config | 310 | // Linux Ethernet/RNDIS gadget, mostly on PXA, second config |
| 311 | // e.g. Gumstix, current OpenZaurus, ... | 311 | // e.g. Gumstix, current OpenZaurus, ... or anything else |
| 312 | USB_DEVICE_VER (0x0525, 0xa4a2, 0x0203, 0x0203), | 312 | // that just enables this gadget option. |
| 313 | USB_DEVICE (0x0525, 0xa4a2), | ||
| 313 | .driver_info = (unsigned long) &linuxdev_info, | 314 | .driver_info = (unsigned long) &linuxdev_info, |
| 314 | }, | 315 | }, |
| 315 | #endif | 316 | #endif |
diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c index 2138535f2339..73acbd244aa1 100644 --- a/drivers/net/usb/pegasus.c +++ b/drivers/net/usb/pegasus.c | |||
| @@ -297,7 +297,7 @@ static int update_eth_regs_async(pegasus_t * pegasus) | |||
| 297 | 297 | ||
| 298 | pegasus->dr.bRequestType = PEGASUS_REQT_WRITE; | 298 | pegasus->dr.bRequestType = PEGASUS_REQT_WRITE; |
| 299 | pegasus->dr.bRequest = PEGASUS_REQ_SET_REGS; | 299 | pegasus->dr.bRequest = PEGASUS_REQ_SET_REGS; |
| 300 | pegasus->dr.wValue = 0; | 300 | pegasus->dr.wValue = cpu_to_le16(0); |
| 301 | pegasus->dr.wIndex = cpu_to_le16(EthCtrl0); | 301 | pegasus->dr.wIndex = cpu_to_le16(EthCtrl0); |
| 302 | pegasus->dr.wLength = cpu_to_le16(3); | 302 | pegasus->dr.wLength = cpu_to_le16(3); |
| 303 | pegasus->ctrl_urb->transfer_buffer_length = 3; | 303 | pegasus->ctrl_urb->transfer_buffer_length = 3; |
| @@ -446,11 +446,12 @@ static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data) | |||
| 446 | int i; | 446 | int i; |
| 447 | __u8 tmp, d[4] = { 0x3f, 0, 0, EPROM_WRITE }; | 447 | __u8 tmp, d[4] = { 0x3f, 0, 0, EPROM_WRITE }; |
| 448 | int ret; | 448 | int ret; |
| 449 | __le16 le_data = cpu_to_le16(data); | ||
| 449 | 450 | ||
| 450 | set_registers(pegasus, EpromOffset, 4, d); | 451 | set_registers(pegasus, EpromOffset, 4, d); |
| 451 | enable_eprom_write(pegasus); | 452 | enable_eprom_write(pegasus); |
| 452 | set_register(pegasus, EpromOffset, index); | 453 | set_register(pegasus, EpromOffset, index); |
| 453 | set_registers(pegasus, EpromData, 2, &data); | 454 | set_registers(pegasus, EpromData, 2, &le_data); |
| 454 | set_register(pegasus, EpromCtrl, EPROM_WRITE); | 455 | set_register(pegasus, EpromCtrl, EPROM_WRITE); |
| 455 | 456 | ||
| 456 | for (i = 0; i < REG_TIMEOUT; i++) { | 457 | for (i = 0; i < REG_TIMEOUT; i++) { |
| @@ -923,29 +924,32 @@ static struct net_device_stats *pegasus_netdev_stats(struct net_device *dev) | |||
| 923 | 924 | ||
| 924 | static inline void disable_net_traffic(pegasus_t * pegasus) | 925 | static inline void disable_net_traffic(pegasus_t * pegasus) |
| 925 | { | 926 | { |
| 926 | int tmp = 0; | 927 | __le16 tmp = cpu_to_le16(0); |
| 927 | 928 | ||
| 928 | set_registers(pegasus, EthCtrl0, 2, &tmp); | 929 | set_registers(pegasus, EthCtrl0, sizeof(tmp), &tmp); |
| 929 | } | 930 | } |
| 930 | 931 | ||
| 931 | static inline void get_interrupt_interval(pegasus_t * pegasus) | 932 | static inline void get_interrupt_interval(pegasus_t * pegasus) |
| 932 | { | 933 | { |
| 933 | __u8 data[2]; | 934 | u16 data; |
| 935 | u8 interval; | ||
| 934 | 936 | ||
| 935 | read_eprom_word(pegasus, 4, (__u16 *) data); | 937 | read_eprom_word(pegasus, 4, &data); |
| 938 | interval = data >> 8; | ||
| 936 | if (pegasus->usb->speed != USB_SPEED_HIGH) { | 939 | if (pegasus->usb->speed != USB_SPEED_HIGH) { |
| 937 | if (data[1] < 0x80) { | 940 | if (interval < 0x80) { |
| 938 | if (netif_msg_timer(pegasus)) | 941 | if (netif_msg_timer(pegasus)) |
| 939 | dev_info(&pegasus->intf->dev, "intr interval " | 942 | dev_info(&pegasus->intf->dev, "intr interval " |
| 940 | "changed from %ums to %ums\n", | 943 | "changed from %ums to %ums\n", |
| 941 | data[1], 0x80); | 944 | interval, 0x80); |
| 942 | data[1] = 0x80; | 945 | interval = 0x80; |
| 946 | data = (data & 0x00FF) | ((u16)interval << 8); | ||
| 943 | #ifdef PEGASUS_WRITE_EEPROM | 947 | #ifdef PEGASUS_WRITE_EEPROM |
| 944 | write_eprom_word(pegasus, 4, *(__u16 *) data); | 948 | write_eprom_word(pegasus, 4, data); |
| 945 | #endif | 949 | #endif |
| 946 | } | 950 | } |
| 947 | } | 951 | } |
| 948 | pegasus->intr_interval = data[1]; | 952 | pegasus->intr_interval = interval; |
| 949 | } | 953 | } |
| 950 | 954 | ||
| 951 | static void set_carrier(struct net_device *net) | 955 | static void set_carrier(struct net_device *net) |
| @@ -1299,7 +1303,8 @@ static int pegasus_blacklisted(struct usb_device *udev) | |||
| 1299 | /* Special quirk to keep the driver from handling the Belkin Bluetooth | 1303 | /* Special quirk to keep the driver from handling the Belkin Bluetooth |
| 1300 | * dongle which happens to have the same ID. | 1304 | * dongle which happens to have the same ID. |
| 1301 | */ | 1305 | */ |
| 1302 | if ((udd->idVendor == VENDOR_BELKIN && udd->idProduct == 0x0121) && | 1306 | if ((udd->idVendor == cpu_to_le16(VENDOR_BELKIN)) && |
| 1307 | (udd->idProduct == cpu_to_le16(0x0121)) && | ||
| 1303 | (udd->bDeviceClass == USB_CLASS_WIRELESS_CONTROLLER) && | 1308 | (udd->bDeviceClass == USB_CLASS_WIRELESS_CONTROLLER) && |
| 1304 | (udd->bDeviceProtocol == 1)) | 1309 | (udd->bDeviceProtocol == 1)) |
| 1305 | return 1; | 1310 | return 1; |
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index b02f7adff5dc..3ba35956327a 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c | |||
| @@ -1847,7 +1847,7 @@ static void velocity_free_tx_buf(struct velocity_info *vptr, struct velocity_td_ | |||
| 1847 | */ | 1847 | */ |
| 1848 | if (tdinfo->skb_dma) { | 1848 | if (tdinfo->skb_dma) { |
| 1849 | 1849 | ||
| 1850 | pktlen = (skb->len > ETH_ZLEN ? : ETH_ZLEN); | 1850 | pktlen = max_t(unsigned int, skb->len, ETH_ZLEN); |
| 1851 | for (i = 0; i < tdinfo->nskb_dma; i++) { | 1851 | for (i = 0; i < tdinfo->nskb_dma; i++) { |
| 1852 | #ifdef VELOCITY_ZERO_COPY_SUPPORT | 1852 | #ifdef VELOCITY_ZERO_COPY_SUPPORT |
| 1853 | pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i], le16_to_cpu(td->tdesc1.len), PCI_DMA_TODEVICE); | 1853 | pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i], le16_to_cpu(td->tdesc1.len), PCI_DMA_TODEVICE); |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 55f7de09d134..ea045151f953 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
| @@ -538,6 +538,7 @@ ath5k_pci_probe(struct pci_dev *pdev, | |||
| 538 | sc->iobase = mem; /* So we can unmap it on detach */ | 538 | sc->iobase = mem; /* So we can unmap it on detach */ |
| 539 | sc->cachelsz = csz * sizeof(u32); /* convert to bytes */ | 539 | sc->cachelsz = csz * sizeof(u32); /* convert to bytes */ |
| 540 | sc->opmode = NL80211_IFTYPE_STATION; | 540 | sc->opmode = NL80211_IFTYPE_STATION; |
| 541 | sc->bintval = 1000; | ||
| 541 | mutex_init(&sc->lock); | 542 | mutex_init(&sc->lock); |
| 542 | spin_lock_init(&sc->rxbuflock); | 543 | spin_lock_init(&sc->rxbuflock); |
| 543 | spin_lock_init(&sc->txbuflock); | 544 | spin_lock_init(&sc->txbuflock); |
| @@ -686,6 +687,13 @@ ath5k_pci_resume(struct pci_dev *pdev) | |||
| 686 | if (err) | 687 | if (err) |
| 687 | return err; | 688 | return err; |
| 688 | 689 | ||
| 690 | /* | ||
| 691 | * Suspend/Resume resets the PCI configuration space, so we have to | ||
| 692 | * re-disable the RETRY_TIMEOUT register (0x41) to keep | ||
| 693 | * PCI Tx retries from interfering with C3 CPU state | ||
| 694 | */ | ||
| 695 | pci_write_config_byte(pdev, 0x41, 0); | ||
| 696 | |||
| 689 | err = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc); | 697 | err = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc); |
| 690 | if (err) { | 698 | if (err) { |
| 691 | ATH5K_ERR(sc, "request_irq failed\n"); | 699 | ATH5K_ERR(sc, "request_irq failed\n"); |
| @@ -2748,9 +2756,6 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, | |||
| 2748 | goto end; | 2756 | goto end; |
| 2749 | } | 2757 | } |
| 2750 | 2758 | ||
| 2751 | /* Set to a reasonable value. Note that this will | ||
| 2752 | * be set to mac80211's value at ath5k_config(). */ | ||
| 2753 | sc->bintval = 1000; | ||
| 2754 | ath5k_hw_set_lladdr(sc->ah, conf->mac_addr); | 2759 | ath5k_hw_set_lladdr(sc->ah, conf->mac_addr); |
| 2755 | 2760 | ||
| 2756 | ret = 0; | 2761 | ret = 0; |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 9f49a3251d4d..66a6c1f5022a 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
| @@ -1196,8 +1196,8 @@ void ath_radio_disable(struct ath_softc *sc) | |||
| 1196 | 1196 | ||
| 1197 | ath9k_hw_phy_disable(ah); | 1197 | ath9k_hw_phy_disable(ah); |
| 1198 | ath9k_hw_configpcipowersave(ah, 1); | 1198 | ath9k_hw_configpcipowersave(ah, 1); |
| 1199 | ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); | ||
| 1200 | ath9k_ps_restore(sc); | 1199 | ath9k_ps_restore(sc); |
| 1200 | ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); | ||
| 1201 | } | 1201 | } |
| 1202 | 1202 | ||
| 1203 | /*******************/ | 1203 | /*******************/ |
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index ccdf20a2e9be..170c5b32e49b 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
| @@ -87,6 +87,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 87 | struct ath_softc *sc; | 87 | struct ath_softc *sc; |
| 88 | struct ieee80211_hw *hw; | 88 | struct ieee80211_hw *hw; |
| 89 | u8 csz; | 89 | u8 csz; |
| 90 | u32 val; | ||
| 90 | int ret = 0; | 91 | int ret = 0; |
| 91 | struct ath_hw *ah; | 92 | struct ath_hw *ah; |
| 92 | 93 | ||
| @@ -133,6 +134,14 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 133 | 134 | ||
| 134 | pci_set_master(pdev); | 135 | pci_set_master(pdev); |
| 135 | 136 | ||
| 137 | /* | ||
| 138 | * Disable the RETRY_TIMEOUT register (0x41) to keep | ||
| 139 | * PCI Tx retries from interfering with C3 CPU state. | ||
| 140 | */ | ||
| 141 | pci_read_config_dword(pdev, 0x40, &val); | ||
| 142 | if ((val & 0x0000ff00) != 0) | ||
| 143 | pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); | ||
| 144 | |||
| 136 | ret = pci_request_region(pdev, 0, "ath9k"); | 145 | ret = pci_request_region(pdev, 0, "ath9k"); |
| 137 | if (ret) { | 146 | if (ret) { |
| 138 | dev_err(&pdev->dev, "PCI memory region reserve error\n"); | 147 | dev_err(&pdev->dev, "PCI memory region reserve error\n"); |
| @@ -239,12 +248,21 @@ static int ath_pci_resume(struct pci_dev *pdev) | |||
| 239 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | 248 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); |
| 240 | struct ath_wiphy *aphy = hw->priv; | 249 | struct ath_wiphy *aphy = hw->priv; |
| 241 | struct ath_softc *sc = aphy->sc; | 250 | struct ath_softc *sc = aphy->sc; |
| 251 | u32 val; | ||
| 242 | int err; | 252 | int err; |
| 243 | 253 | ||
| 244 | err = pci_enable_device(pdev); | 254 | err = pci_enable_device(pdev); |
| 245 | if (err) | 255 | if (err) |
| 246 | return err; | 256 | return err; |
| 247 | pci_restore_state(pdev); | 257 | pci_restore_state(pdev); |
| 258 | /* | ||
| 259 | * Suspend/Resume resets the PCI configuration space, so we have to | ||
| 260 | * re-disable the RETRY_TIMEOUT register (0x41) to keep | ||
| 261 | * PCI Tx retries from interfering with C3 CPU state | ||
| 262 | */ | ||
| 263 | pci_read_config_dword(pdev, 0x40, &val); | ||
| 264 | if ((val & 0x0000ff00) != 0) | ||
| 265 | pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); | ||
| 248 | 266 | ||
| 249 | /* Enable LED */ | 267 | /* Enable LED */ |
| 250 | ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN, | 268 | ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN, |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index f99f3a76df3f..cece1c4c6bda 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
| @@ -539,11 +539,14 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) | |||
| 539 | if (ath_beacon_dtim_pending_cab(skb)) { | 539 | if (ath_beacon_dtim_pending_cab(skb)) { |
| 540 | /* | 540 | /* |
| 541 | * Remain awake waiting for buffered broadcast/multicast | 541 | * Remain awake waiting for buffered broadcast/multicast |
| 542 | * frames. | 542 | * frames. If the last broadcast/multicast frame is not |
| 543 | * received properly, the next beacon frame will work as | ||
| 544 | * a backup trigger for returning into NETWORK SLEEP state, | ||
| 545 | * so we are waiting for it as well. | ||
| 543 | */ | 546 | */ |
| 544 | DPRINTF(sc, ATH_DBG_PS, "Received DTIM beacon indicating " | 547 | DPRINTF(sc, ATH_DBG_PS, "Received DTIM beacon indicating " |
| 545 | "buffered broadcast/multicast frame(s)\n"); | 548 | "buffered broadcast/multicast frame(s)\n"); |
| 546 | sc->sc_flags |= SC_OP_WAIT_FOR_CAB; | 549 | sc->sc_flags |= SC_OP_WAIT_FOR_CAB | SC_OP_WAIT_FOR_BEACON; |
| 547 | return; | 550 | return; |
| 548 | } | 551 | } |
| 549 | 552 | ||
diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index 635c16ee6186..77c339f8516c 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h | |||
| @@ -288,6 +288,7 @@ struct iwm_priv { | |||
| 288 | u8 *eeprom; | 288 | u8 *eeprom; |
| 289 | struct timer_list watchdog; | 289 | struct timer_list watchdog; |
| 290 | struct work_struct reset_worker; | 290 | struct work_struct reset_worker; |
| 291 | struct mutex mutex; | ||
| 291 | struct rfkill *rfkill; | 292 | struct rfkill *rfkill; |
| 292 | 293 | ||
| 293 | char private[0] __attribute__((__aligned__(NETDEV_ALIGN))); | 294 | char private[0] __attribute__((__aligned__(NETDEV_ALIGN))); |
| @@ -315,8 +316,11 @@ extern const struct iw_handler_def iwm_iw_handler_def; | |||
| 315 | void *iwm_if_alloc(int sizeof_bus, struct device *dev, | 316 | void *iwm_if_alloc(int sizeof_bus, struct device *dev, |
| 316 | struct iwm_if_ops *if_ops); | 317 | struct iwm_if_ops *if_ops); |
| 317 | void iwm_if_free(struct iwm_priv *iwm); | 318 | void iwm_if_free(struct iwm_priv *iwm); |
| 319 | int iwm_if_add(struct iwm_priv *iwm); | ||
| 320 | void iwm_if_remove(struct iwm_priv *iwm); | ||
| 318 | int iwm_mode_to_nl80211_iftype(int mode); | 321 | int iwm_mode_to_nl80211_iftype(int mode); |
| 319 | int iwm_priv_init(struct iwm_priv *iwm); | 322 | int iwm_priv_init(struct iwm_priv *iwm); |
| 323 | void iwm_priv_deinit(struct iwm_priv *iwm); | ||
| 320 | void iwm_reset(struct iwm_priv *iwm); | 324 | void iwm_reset(struct iwm_priv *iwm); |
| 321 | void iwm_tx_credit_init_pools(struct iwm_priv *iwm, | 325 | void iwm_tx_credit_init_pools(struct iwm_priv *iwm, |
| 322 | struct iwm_umac_notif_alive *alive); | 326 | struct iwm_umac_notif_alive *alive); |
diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c index 6a2640f16b6d..8be206d58222 100644 --- a/drivers/net/wireless/iwmc3200wifi/main.c +++ b/drivers/net/wireless/iwmc3200wifi/main.c | |||
| @@ -112,6 +112,9 @@ static void iwm_statistics_request(struct work_struct *work) | |||
| 112 | iwm_send_umac_stats_req(iwm, 0); | 112 | iwm_send_umac_stats_req(iwm, 0); |
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | int __iwm_up(struct iwm_priv *iwm); | ||
| 116 | int __iwm_down(struct iwm_priv *iwm); | ||
| 117 | |||
| 115 | static void iwm_reset_worker(struct work_struct *work) | 118 | static void iwm_reset_worker(struct work_struct *work) |
| 116 | { | 119 | { |
| 117 | struct iwm_priv *iwm; | 120 | struct iwm_priv *iwm; |
| @@ -120,6 +123,19 @@ static void iwm_reset_worker(struct work_struct *work) | |||
| 120 | 123 | ||
| 121 | iwm = container_of(work, struct iwm_priv, reset_worker); | 124 | iwm = container_of(work, struct iwm_priv, reset_worker); |
| 122 | 125 | ||
| 126 | /* | ||
| 127 | * XXX: The iwm->mutex is introduced purely for this reset work, | ||
| 128 | * because the other users for iwm_up and iwm_down are only netdev | ||
| 129 | * ndo_open and ndo_stop which are already protected by rtnl. | ||
| 130 | * Please remove iwm->mutex together if iwm_reset_worker() is not | ||
| 131 | * required in the future. | ||
| 132 | */ | ||
| 133 | if (!mutex_trylock(&iwm->mutex)) { | ||
| 134 | IWM_WARN(iwm, "We are in the middle of interface bringing " | ||
| 135 | "UP/DOWN. Skip driver resetting.\n"); | ||
| 136 | return; | ||
| 137 | } | ||
| 138 | |||
| 123 | if (iwm->umac_profile_active) { | 139 | if (iwm->umac_profile_active) { |
| 124 | profile = kmalloc(sizeof(struct iwm_umac_profile), GFP_KERNEL); | 140 | profile = kmalloc(sizeof(struct iwm_umac_profile), GFP_KERNEL); |
| 125 | if (profile) | 141 | if (profile) |
| @@ -128,10 +144,10 @@ static void iwm_reset_worker(struct work_struct *work) | |||
| 128 | IWM_ERR(iwm, "Couldn't alloc memory for profile\n"); | 144 | IWM_ERR(iwm, "Couldn't alloc memory for profile\n"); |
| 129 | } | 145 | } |
| 130 | 146 | ||
| 131 | iwm_down(iwm); | 147 | __iwm_down(iwm); |
| 132 | 148 | ||
| 133 | while (retry++ < 3) { | 149 | while (retry++ < 3) { |
| 134 | ret = iwm_up(iwm); | 150 | ret = __iwm_up(iwm); |
| 135 | if (!ret) | 151 | if (!ret) |
| 136 | break; | 152 | break; |
| 137 | 153 | ||
| @@ -142,7 +158,7 @@ static void iwm_reset_worker(struct work_struct *work) | |||
| 142 | IWM_WARN(iwm, "iwm_up() failed: %d\n", ret); | 158 | IWM_WARN(iwm, "iwm_up() failed: %d\n", ret); |
| 143 | 159 | ||
| 144 | kfree(profile); | 160 | kfree(profile); |
| 145 | return; | 161 | goto out; |
| 146 | } | 162 | } |
| 147 | 163 | ||
| 148 | if (profile) { | 164 | if (profile) { |
| @@ -151,6 +167,9 @@ static void iwm_reset_worker(struct work_struct *work) | |||
| 151 | iwm_send_mlme_profile(iwm); | 167 | iwm_send_mlme_profile(iwm); |
| 152 | kfree(profile); | 168 | kfree(profile); |
| 153 | } | 169 | } |
| 170 | |||
| 171 | out: | ||
| 172 | mutex_unlock(&iwm->mutex); | ||
| 154 | } | 173 | } |
| 155 | 174 | ||
| 156 | static void iwm_watchdog(unsigned long data) | 175 | static void iwm_watchdog(unsigned long data) |
| @@ -215,10 +234,21 @@ int iwm_priv_init(struct iwm_priv *iwm) | |||
| 215 | init_timer(&iwm->watchdog); | 234 | init_timer(&iwm->watchdog); |
| 216 | iwm->watchdog.function = iwm_watchdog; | 235 | iwm->watchdog.function = iwm_watchdog; |
| 217 | iwm->watchdog.data = (unsigned long)iwm; | 236 | iwm->watchdog.data = (unsigned long)iwm; |
| 237 | mutex_init(&iwm->mutex); | ||
| 218 | 238 | ||
| 219 | return 0; | 239 | return 0; |
| 220 | } | 240 | } |
| 221 | 241 | ||
| 242 | void iwm_priv_deinit(struct iwm_priv *iwm) | ||
| 243 | { | ||
| 244 | int i; | ||
| 245 | |||
| 246 | for (i = 0; i < IWM_TX_QUEUES; i++) | ||
| 247 | destroy_workqueue(iwm->txq[i].wq); | ||
| 248 | |||
| 249 | destroy_workqueue(iwm->rx_wq); | ||
| 250 | } | ||
| 251 | |||
| 222 | /* | 252 | /* |
| 223 | * We reset all the structures, and we reset the UMAC. | 253 | * We reset all the structures, and we reset the UMAC. |
| 224 | * After calling this routine, you're expected to reload | 254 | * After calling this routine, you're expected to reload |
| @@ -466,7 +496,7 @@ void iwm_link_off(struct iwm_priv *iwm) | |||
| 466 | 496 | ||
| 467 | iwm_rx_free(iwm); | 497 | iwm_rx_free(iwm); |
| 468 | 498 | ||
| 469 | cancel_delayed_work(&iwm->stats_request); | 499 | cancel_delayed_work_sync(&iwm->stats_request); |
| 470 | memset(wstats, 0, sizeof(struct iw_statistics)); | 500 | memset(wstats, 0, sizeof(struct iw_statistics)); |
| 471 | wstats->qual.updated = IW_QUAL_ALL_INVALID; | 501 | wstats->qual.updated = IW_QUAL_ALL_INVALID; |
| 472 | 502 | ||
| @@ -511,7 +541,7 @@ static int iwm_channels_init(struct iwm_priv *iwm) | |||
| 511 | return 0; | 541 | return 0; |
| 512 | } | 542 | } |
| 513 | 543 | ||
| 514 | int iwm_up(struct iwm_priv *iwm) | 544 | int __iwm_up(struct iwm_priv *iwm) |
| 515 | { | 545 | { |
| 516 | int ret; | 546 | int ret; |
| 517 | struct iwm_notif *notif_reboot, *notif_ack = NULL; | 547 | struct iwm_notif *notif_reboot, *notif_ack = NULL; |
| @@ -647,7 +677,18 @@ int iwm_up(struct iwm_priv *iwm) | |||
| 647 | return -EIO; | 677 | return -EIO; |
| 648 | } | 678 | } |
| 649 | 679 | ||
| 650 | int iwm_down(struct iwm_priv *iwm) | 680 | int iwm_up(struct iwm_priv *iwm) |
| 681 | { | ||
| 682 | int ret; | ||
| 683 | |||
| 684 | mutex_lock(&iwm->mutex); | ||
| 685 | ret = __iwm_up(iwm); | ||
| 686 | mutex_unlock(&iwm->mutex); | ||
| 687 | |||
| 688 | return ret; | ||
| 689 | } | ||
| 690 | |||
| 691 | int __iwm_down(struct iwm_priv *iwm) | ||
| 651 | { | 692 | { |
| 652 | int ret; | 693 | int ret; |
| 653 | 694 | ||
| @@ -678,3 +719,14 @@ int iwm_down(struct iwm_priv *iwm) | |||
| 678 | 719 | ||
| 679 | return 0; | 720 | return 0; |
| 680 | } | 721 | } |
| 722 | |||
| 723 | int iwm_down(struct iwm_priv *iwm) | ||
| 724 | { | ||
| 725 | int ret; | ||
| 726 | |||
| 727 | mutex_lock(&iwm->mutex); | ||
| 728 | ret = __iwm_down(iwm); | ||
| 729 | mutex_unlock(&iwm->mutex); | ||
| 730 | |||
| 731 | return ret; | ||
| 732 | } | ||
diff --git a/drivers/net/wireless/iwmc3200wifi/netdev.c b/drivers/net/wireless/iwmc3200wifi/netdev.c index 68e2c3b6c7a1..aaa20c6885c8 100644 --- a/drivers/net/wireless/iwmc3200wifi/netdev.c +++ b/drivers/net/wireless/iwmc3200wifi/netdev.c | |||
| @@ -114,32 +114,31 @@ void *iwm_if_alloc(int sizeof_bus, struct device *dev, | |||
| 114 | iwm = wdev_to_iwm(wdev); | 114 | iwm = wdev_to_iwm(wdev); |
| 115 | iwm->bus_ops = if_ops; | 115 | iwm->bus_ops = if_ops; |
| 116 | iwm->wdev = wdev; | 116 | iwm->wdev = wdev; |
| 117 | iwm_priv_init(iwm); | 117 | |
| 118 | ret = iwm_priv_init(iwm); | ||
| 119 | if (ret) { | ||
| 120 | dev_err(dev, "failed to init iwm_priv\n"); | ||
| 121 | goto out_wdev; | ||
| 122 | } | ||
| 123 | |||
| 118 | wdev->iftype = iwm_mode_to_nl80211_iftype(iwm->conf.mode); | 124 | wdev->iftype = iwm_mode_to_nl80211_iftype(iwm->conf.mode); |
| 119 | 125 | ||
| 120 | ndev = alloc_netdev_mq(0, "wlan%d", ether_setup, | 126 | ndev = alloc_netdev_mq(0, "wlan%d", ether_setup, IWM_TX_QUEUES); |
| 121 | IWM_TX_QUEUES); | ||
| 122 | if (!ndev) { | 127 | if (!ndev) { |
| 123 | dev_err(dev, "no memory for network device instance\n"); | 128 | dev_err(dev, "no memory for network device instance\n"); |
| 124 | goto out_wdev; | 129 | goto out_priv; |
| 125 | } | 130 | } |
| 126 | 131 | ||
| 127 | ndev->netdev_ops = &iwm_netdev_ops; | 132 | ndev->netdev_ops = &iwm_netdev_ops; |
| 128 | ndev->wireless_handlers = &iwm_iw_handler_def; | 133 | ndev->wireless_handlers = &iwm_iw_handler_def; |
| 129 | ndev->ieee80211_ptr = wdev; | 134 | ndev->ieee80211_ptr = wdev; |
| 130 | SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); | 135 | SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); |
| 131 | ret = register_netdev(ndev); | ||
| 132 | if (ret < 0) { | ||
| 133 | dev_err(dev, "Failed to register netdev: %d\n", ret); | ||
| 134 | goto out_ndev; | ||
| 135 | } | ||
| 136 | |||
| 137 | wdev->netdev = ndev; | 136 | wdev->netdev = ndev; |
| 138 | 137 | ||
| 139 | return iwm; | 138 | return iwm; |
| 140 | 139 | ||
| 141 | out_ndev: | 140 | out_priv: |
| 142 | free_netdev(ndev); | 141 | iwm_priv_deinit(iwm); |
| 143 | 142 | ||
| 144 | out_wdev: | 143 | out_wdev: |
| 145 | iwm_wdev_free(iwm); | 144 | iwm_wdev_free(iwm); |
| @@ -148,15 +147,29 @@ void *iwm_if_alloc(int sizeof_bus, struct device *dev, | |||
| 148 | 147 | ||
| 149 | void iwm_if_free(struct iwm_priv *iwm) | 148 | void iwm_if_free(struct iwm_priv *iwm) |
| 150 | { | 149 | { |
| 151 | int i; | ||
| 152 | |||
| 153 | if (!iwm_to_ndev(iwm)) | 150 | if (!iwm_to_ndev(iwm)) |
| 154 | return; | 151 | return; |
| 155 | 152 | ||
| 156 | unregister_netdev(iwm_to_ndev(iwm)); | ||
| 157 | free_netdev(iwm_to_ndev(iwm)); | 153 | free_netdev(iwm_to_ndev(iwm)); |
| 158 | iwm_wdev_free(iwm); | 154 | iwm_wdev_free(iwm); |
| 159 | destroy_workqueue(iwm->rx_wq); | 155 | iwm_priv_deinit(iwm); |
| 160 | for (i = 0; i < IWM_TX_QUEUES; i++) | 156 | } |
| 161 | destroy_workqueue(iwm->txq[i].wq); | 157 | |
| 158 | int iwm_if_add(struct iwm_priv *iwm) | ||
| 159 | { | ||
| 160 | struct net_device *ndev = iwm_to_ndev(iwm); | ||
| 161 | int ret; | ||
| 162 | |||
| 163 | ret = register_netdev(ndev); | ||
| 164 | if (ret < 0) { | ||
| 165 | dev_err(&ndev->dev, "Failed to register netdev: %d\n", ret); | ||
| 166 | return ret; | ||
| 167 | } | ||
| 168 | |||
| 169 | return 0; | ||
| 170 | } | ||
| 171 | |||
| 172 | void iwm_if_remove(struct iwm_priv *iwm) | ||
| 173 | { | ||
| 174 | unregister_netdev(iwm_to_ndev(iwm)); | ||
| 162 | } | 175 | } |
diff --git a/drivers/net/wireless/iwmc3200wifi/sdio.c b/drivers/net/wireless/iwmc3200wifi/sdio.c index b54da677b371..916681837fd2 100644 --- a/drivers/net/wireless/iwmc3200wifi/sdio.c +++ b/drivers/net/wireless/iwmc3200wifi/sdio.c | |||
| @@ -454,10 +454,18 @@ static int iwm_sdio_probe(struct sdio_func *func, | |||
| 454 | 454 | ||
| 455 | INIT_WORK(&hw->isr_worker, iwm_sdio_isr_worker); | 455 | INIT_WORK(&hw->isr_worker, iwm_sdio_isr_worker); |
| 456 | 456 | ||
| 457 | ret = iwm_if_add(iwm); | ||
| 458 | if (ret) { | ||
| 459 | dev_err(dev, "add SDIO interface failed\n"); | ||
| 460 | goto destroy_wq; | ||
| 461 | } | ||
| 462 | |||
| 457 | dev_info(dev, "IWM SDIO probe\n"); | 463 | dev_info(dev, "IWM SDIO probe\n"); |
| 458 | 464 | ||
| 459 | return 0; | 465 | return 0; |
| 460 | 466 | ||
| 467 | destroy_wq: | ||
| 468 | destroy_workqueue(hw->isr_wq); | ||
| 461 | debugfs_exit: | 469 | debugfs_exit: |
| 462 | iwm_debugfs_exit(iwm); | 470 | iwm_debugfs_exit(iwm); |
| 463 | if_free: | 471 | if_free: |
| @@ -471,9 +479,10 @@ static void iwm_sdio_remove(struct sdio_func *func) | |||
| 471 | struct iwm_priv *iwm = hw_to_iwm(hw); | 479 | struct iwm_priv *iwm = hw_to_iwm(hw); |
| 472 | struct device *dev = &func->dev; | 480 | struct device *dev = &func->dev; |
| 473 | 481 | ||
| 482 | iwm_if_remove(iwm); | ||
| 483 | destroy_workqueue(hw->isr_wq); | ||
| 474 | iwm_debugfs_exit(iwm); | 484 | iwm_debugfs_exit(iwm); |
| 475 | iwm_if_free(iwm); | 485 | iwm_if_free(iwm); |
| 476 | destroy_workqueue(hw->isr_wq); | ||
| 477 | 486 | ||
| 478 | sdio_set_drvdata(func, NULL); | 487 | sdio_set_drvdata(func, NULL); |
| 479 | 488 | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index f0e5e943f6e3..14a19baff214 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c | |||
| @@ -67,6 +67,7 @@ static struct usb_device_id usb_ids[] = { | |||
| 67 | { USB_DEVICE(0x079b, 0x0062), .driver_info = DEVICE_ZD1211B }, | 67 | { USB_DEVICE(0x079b, 0x0062), .driver_info = DEVICE_ZD1211B }, |
| 68 | { USB_DEVICE(0x1582, 0x6003), .driver_info = DEVICE_ZD1211B }, | 68 | { USB_DEVICE(0x1582, 0x6003), .driver_info = DEVICE_ZD1211B }, |
| 69 | { USB_DEVICE(0x050d, 0x705c), .driver_info = DEVICE_ZD1211B }, | 69 | { USB_DEVICE(0x050d, 0x705c), .driver_info = DEVICE_ZD1211B }, |
| 70 | { USB_DEVICE(0x083a, 0xe503), .driver_info = DEVICE_ZD1211B }, | ||
| 70 | { USB_DEVICE(0x083a, 0xe506), .driver_info = DEVICE_ZD1211B }, | 71 | { USB_DEVICE(0x083a, 0xe506), .driver_info = DEVICE_ZD1211B }, |
| 71 | { USB_DEVICE(0x083a, 0x4505), .driver_info = DEVICE_ZD1211B }, | 72 | { USB_DEVICE(0x083a, 0x4505), .driver_info = DEVICE_ZD1211B }, |
| 72 | { USB_DEVICE(0x0471, 0x1236), .driver_info = DEVICE_ZD1211B }, | 73 | { USB_DEVICE(0x0471, 0x1236), .driver_info = DEVICE_ZD1211B }, |
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 09a503e5da6a..be2fd6f91639 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c | |||
| @@ -958,12 +958,12 @@ static void acer_rfkill_update(struct work_struct *ignored) | |||
| 958 | 958 | ||
| 959 | status = get_u32(&state, ACER_CAP_WIRELESS); | 959 | status = get_u32(&state, ACER_CAP_WIRELESS); |
| 960 | if (ACPI_SUCCESS(status)) | 960 | if (ACPI_SUCCESS(status)) |
| 961 | rfkill_set_sw_state(wireless_rfkill, !!state); | 961 | rfkill_set_sw_state(wireless_rfkill, !state); |
| 962 | 962 | ||
| 963 | if (has_cap(ACER_CAP_BLUETOOTH)) { | 963 | if (has_cap(ACER_CAP_BLUETOOTH)) { |
| 964 | status = get_u32(&state, ACER_CAP_BLUETOOTH); | 964 | status = get_u32(&state, ACER_CAP_BLUETOOTH); |
| 965 | if (ACPI_SUCCESS(status)) | 965 | if (ACPI_SUCCESS(status)) |
| 966 | rfkill_set_sw_state(bluetooth_rfkill, !!state); | 966 | rfkill_set_sw_state(bluetooth_rfkill, !state); |
| 967 | } | 967 | } |
| 968 | 968 | ||
| 969 | schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ)); | 969 | schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ)); |
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 03bf522bd7ab..8153b3e59189 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c | |||
| @@ -180,6 +180,7 @@ static struct key_entry eeepc_keymap[] = { | |||
| 180 | */ | 180 | */ |
| 181 | static int eeepc_hotk_add(struct acpi_device *device); | 181 | static int eeepc_hotk_add(struct acpi_device *device); |
| 182 | static int eeepc_hotk_remove(struct acpi_device *device, int type); | 182 | static int eeepc_hotk_remove(struct acpi_device *device, int type); |
| 183 | static int eeepc_hotk_resume(struct acpi_device *device); | ||
| 183 | 184 | ||
| 184 | static const struct acpi_device_id eeepc_device_ids[] = { | 185 | static const struct acpi_device_id eeepc_device_ids[] = { |
| 185 | {EEEPC_HOTK_HID, 0}, | 186 | {EEEPC_HOTK_HID, 0}, |
| @@ -194,6 +195,7 @@ static struct acpi_driver eeepc_hotk_driver = { | |||
| 194 | .ops = { | 195 | .ops = { |
| 195 | .add = eeepc_hotk_add, | 196 | .add = eeepc_hotk_add, |
| 196 | .remove = eeepc_hotk_remove, | 197 | .remove = eeepc_hotk_remove, |
| 198 | .resume = eeepc_hotk_resume, | ||
| 197 | }, | 199 | }, |
| 198 | }; | 200 | }; |
| 199 | 201 | ||
| @@ -512,15 +514,12 @@ static int notify_brn(void) | |||
| 512 | return -1; | 514 | return -1; |
| 513 | } | 515 | } |
| 514 | 516 | ||
| 515 | static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) | 517 | static void eeepc_rfkill_hotplug(void) |
| 516 | { | 518 | { |
| 517 | struct pci_dev *dev; | 519 | struct pci_dev *dev; |
| 518 | struct pci_bus *bus = pci_find_bus(0, 1); | 520 | struct pci_bus *bus = pci_find_bus(0, 1); |
| 519 | bool blocked; | 521 | bool blocked; |
| 520 | 522 | ||
| 521 | if (event != ACPI_NOTIFY_BUS_CHECK) | ||
| 522 | return; | ||
| 523 | |||
| 524 | if (!bus) { | 523 | if (!bus) { |
| 525 | printk(EEEPC_WARNING "Unable to find PCI bus 1?\n"); | 524 | printk(EEEPC_WARNING "Unable to find PCI bus 1?\n"); |
| 526 | return; | 525 | return; |
| @@ -551,6 +550,14 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) | |||
| 551 | rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill, blocked); | 550 | rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill, blocked); |
| 552 | } | 551 | } |
| 553 | 552 | ||
| 553 | static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) | ||
| 554 | { | ||
| 555 | if (event != ACPI_NOTIFY_BUS_CHECK) | ||
| 556 | return; | ||
| 557 | |||
| 558 | eeepc_rfkill_hotplug(); | ||
| 559 | } | ||
| 560 | |||
| 554 | static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) | 561 | static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) |
| 555 | { | 562 | { |
| 556 | static struct key_entry *key; | 563 | static struct key_entry *key; |
| @@ -675,8 +682,8 @@ static int eeepc_hotk_add(struct acpi_device *device) | |||
| 675 | if (!ehotk->eeepc_wlan_rfkill) | 682 | if (!ehotk->eeepc_wlan_rfkill) |
| 676 | goto wlan_fail; | 683 | goto wlan_fail; |
| 677 | 684 | ||
| 678 | rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill, | 685 | rfkill_init_sw_state(ehotk->eeepc_wlan_rfkill, |
| 679 | get_acpi(CM_ASL_WLAN) != 1); | 686 | get_acpi(CM_ASL_WLAN) != 1); |
| 680 | result = rfkill_register(ehotk->eeepc_wlan_rfkill); | 687 | result = rfkill_register(ehotk->eeepc_wlan_rfkill); |
| 681 | if (result) | 688 | if (result) |
| 682 | goto wlan_fail; | 689 | goto wlan_fail; |
| @@ -693,8 +700,8 @@ static int eeepc_hotk_add(struct acpi_device *device) | |||
| 693 | if (!ehotk->eeepc_bluetooth_rfkill) | 700 | if (!ehotk->eeepc_bluetooth_rfkill) |
| 694 | goto bluetooth_fail; | 701 | goto bluetooth_fail; |
| 695 | 702 | ||
| 696 | rfkill_set_sw_state(ehotk->eeepc_bluetooth_rfkill, | 703 | rfkill_init_sw_state(ehotk->eeepc_bluetooth_rfkill, |
| 697 | get_acpi(CM_ASL_BLUETOOTH) != 1); | 704 | get_acpi(CM_ASL_BLUETOOTH) != 1); |
| 698 | result = rfkill_register(ehotk->eeepc_bluetooth_rfkill); | 705 | result = rfkill_register(ehotk->eeepc_bluetooth_rfkill); |
| 699 | if (result) | 706 | if (result) |
| 700 | goto bluetooth_fail; | 707 | goto bluetooth_fail; |
| @@ -734,6 +741,33 @@ static int eeepc_hotk_remove(struct acpi_device *device, int type) | |||
| 734 | return 0; | 741 | return 0; |
| 735 | } | 742 | } |
| 736 | 743 | ||
| 744 | static int eeepc_hotk_resume(struct acpi_device *device) | ||
| 745 | { | ||
| 746 | if (ehotk->eeepc_wlan_rfkill) { | ||
| 747 | bool wlan; | ||
| 748 | |||
| 749 | /* Workaround - it seems that _PTS disables the wireless | ||
| 750 | without notification or changing the value read by WLAN. | ||
| 751 | Normally this is fine because the correct value is restored | ||
| 752 | from the non-volatile storage on resume, but we need to do | ||
| 753 | it ourself if case suspend is aborted, or we lose wireless. | ||
| 754 | */ | ||
| 755 | wlan = get_acpi(CM_ASL_WLAN); | ||
| 756 | set_acpi(CM_ASL_WLAN, wlan); | ||
| 757 | |||
| 758 | rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill, | ||
| 759 | wlan != 1); | ||
| 760 | |||
| 761 | eeepc_rfkill_hotplug(); | ||
| 762 | } | ||
| 763 | |||
| 764 | if (ehotk->eeepc_bluetooth_rfkill) | ||
| 765 | rfkill_set_sw_state(ehotk->eeepc_bluetooth_rfkill, | ||
| 766 | get_acpi(CM_ASL_BLUETOOTH) != 1); | ||
| 767 | |||
| 768 | return 0; | ||
| 769 | } | ||
| 770 | |||
| 737 | /* | 771 | /* |
| 738 | * Hwmon | 772 | * Hwmon |
| 739 | */ | 773 | */ |
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 86e958539f46..40d64c03278c 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c | |||
| @@ -1163,8 +1163,8 @@ static int __init tpacpi_new_rfkill(const enum tpacpi_rfk_id id, | |||
| 1163 | { | 1163 | { |
| 1164 | struct tpacpi_rfk *atp_rfk; | 1164 | struct tpacpi_rfk *atp_rfk; |
| 1165 | int res; | 1165 | int res; |
| 1166 | bool initial_sw_state = false; | 1166 | bool sw_state = false; |
| 1167 | int initial_sw_status; | 1167 | int sw_status; |
| 1168 | 1168 | ||
| 1169 | BUG_ON(id >= TPACPI_RFK_SW_MAX || tpacpi_rfkill_switches[id]); | 1169 | BUG_ON(id >= TPACPI_RFK_SW_MAX || tpacpi_rfkill_switches[id]); |
| 1170 | 1170 | ||
| @@ -1185,17 +1185,17 @@ static int __init tpacpi_new_rfkill(const enum tpacpi_rfk_id id, | |||
| 1185 | atp_rfk->id = id; | 1185 | atp_rfk->id = id; |
| 1186 | atp_rfk->ops = tp_rfkops; | 1186 | atp_rfk->ops = tp_rfkops; |
| 1187 | 1187 | ||
| 1188 | initial_sw_status = (tp_rfkops->get_status)(); | 1188 | sw_status = (tp_rfkops->get_status)(); |
| 1189 | if (initial_sw_status < 0) { | 1189 | if (sw_status < 0) { |
| 1190 | printk(TPACPI_ERR | 1190 | printk(TPACPI_ERR |
| 1191 | "failed to read initial state for %s, error %d\n", | 1191 | "failed to read initial state for %s, error %d\n", |
| 1192 | name, initial_sw_status); | 1192 | name, sw_status); |
| 1193 | } else { | 1193 | } else { |
| 1194 | initial_sw_state = (initial_sw_status == TPACPI_RFK_RADIO_OFF); | 1194 | sw_state = (sw_status == TPACPI_RFK_RADIO_OFF); |
| 1195 | if (set_default) { | 1195 | if (set_default) { |
| 1196 | /* try to keep the initial state, since we ask the | 1196 | /* try to keep the initial state, since we ask the |
| 1197 | * firmware to preserve it across S5 in NVRAM */ | 1197 | * firmware to preserve it across S5 in NVRAM */ |
| 1198 | rfkill_set_sw_state(atp_rfk->rfkill, initial_sw_state); | 1198 | rfkill_init_sw_state(atp_rfk->rfkill, sw_state); |
| 1199 | } | 1199 | } |
| 1200 | } | 1200 | } |
| 1201 | rfkill_set_hw_state(atp_rfk->rfkill, tpacpi_rfk_check_hwblock_state()); | 1201 | rfkill_set_hw_state(atp_rfk->rfkill, tpacpi_rfk_check_hwblock_state()); |
diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h index 16e39c7a67fc..e73e2429a1b1 100644 --- a/include/linux/rfkill.h +++ b/include/linux/rfkill.h | |||
| @@ -160,8 +160,9 @@ struct rfkill * __must_check rfkill_alloc(const char *name, | |||
| 160 | * the rfkill structure. Before calling this function the driver needs | 160 | * the rfkill structure. Before calling this function the driver needs |
| 161 | * to be ready to service method calls from rfkill. | 161 | * to be ready to service method calls from rfkill. |
| 162 | * | 162 | * |
| 163 | * If the software blocked state is not set before registration, | 163 | * If rfkill_init_sw_state() is not called before registration, |
| 164 | * set_block will be called to initialize it to a default value. | 164 | * set_block() will be called to initialize the software blocked state |
| 165 | * to a default value. | ||
| 165 | * | 166 | * |
| 166 | * If the hardware blocked state is not set before registration, | 167 | * If the hardware blocked state is not set before registration, |
| 167 | * it is assumed to be unblocked. | 168 | * it is assumed to be unblocked. |
| @@ -234,9 +235,11 @@ bool __must_check rfkill_set_hw_state(struct rfkill *rfkill, bool blocked); | |||
| 234 | * rfkill drivers that get events when the soft-blocked state changes | 235 | * rfkill drivers that get events when the soft-blocked state changes |
| 235 | * (yes, some platforms directly act on input but allow changing again) | 236 | * (yes, some platforms directly act on input but allow changing again) |
| 236 | * use this function to notify the rfkill core (and through that also | 237 | * use this function to notify the rfkill core (and through that also |
| 237 | * userspace) of the current state. It is not necessary to notify on | 238 | * userspace) of the current state. |
| 238 | * resume; since hibernation can always change the soft-blocked state, | 239 | * |
| 239 | * the rfkill core will unconditionally restore the previous state. | 240 | * Drivers should also call this function after resume if the state has |
| 241 | * been changed by the user. This only makes sense for "persistent" | ||
| 242 | * devices (see rfkill_init_sw_state()). | ||
| 240 | * | 243 | * |
| 241 | * This function can be called in any context, even from within rfkill | 244 | * This function can be called in any context, even from within rfkill |
| 242 | * callbacks. | 245 | * callbacks. |
| @@ -247,6 +250,22 @@ bool __must_check rfkill_set_hw_state(struct rfkill *rfkill, bool blocked); | |||
| 247 | bool rfkill_set_sw_state(struct rfkill *rfkill, bool blocked); | 250 | bool rfkill_set_sw_state(struct rfkill *rfkill, bool blocked); |
| 248 | 251 | ||
| 249 | /** | 252 | /** |
| 253 | * rfkill_init_sw_state - Initialize persistent software block state | ||
| 254 | * @rfkill: pointer to the rfkill class to modify. | ||
| 255 | * @state: the current software block state to set | ||
| 256 | * | ||
| 257 | * rfkill drivers that preserve their software block state over power off | ||
| 258 | * use this function to notify the rfkill core (and through that also | ||
| 259 | * userspace) of their initial state. It should only be used before | ||
| 260 | * registration. | ||
| 261 | * | ||
| 262 | * In addition, it marks the device as "persistent", an attribute which | ||
| 263 | * can be read by userspace. Persistent devices are expected to preserve | ||
| 264 | * their own state when suspended. | ||
| 265 | */ | ||
| 266 | void rfkill_init_sw_state(struct rfkill *rfkill, bool blocked); | ||
| 267 | |||
| 268 | /** | ||
| 250 | * rfkill_set_states - Set the internal rfkill block states | 269 | * rfkill_set_states - Set the internal rfkill block states |
| 251 | * @rfkill: pointer to the rfkill class to modify. | 270 | * @rfkill: pointer to the rfkill class to modify. |
| 252 | * @sw: the current software block state to set | 271 | * @sw: the current software block state to set |
| @@ -307,6 +326,10 @@ static inline bool rfkill_set_sw_state(struct rfkill *rfkill, bool blocked) | |||
| 307 | return blocked; | 326 | return blocked; |
| 308 | } | 327 | } |
| 309 | 328 | ||
| 329 | static inline void rfkill_init_sw_state(struct rfkill *rfkill, bool blocked) | ||
| 330 | { | ||
| 331 | } | ||
| 332 | |||
| 310 | static inline void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw) | 333 | static inline void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw) |
| 311 | { | 334 | { |
| 312 | } | 335 | } |
diff --git a/include/net/iucv/af_iucv.h b/include/net/iucv/af_iucv.h index 21ee49ffcbaf..f82a1e877372 100644 --- a/include/net/iucv/af_iucv.h +++ b/include/net/iucv/af_iucv.h | |||
| @@ -94,8 +94,6 @@ unsigned int iucv_sock_poll(struct file *file, struct socket *sock, | |||
| 94 | poll_table *wait); | 94 | poll_table *wait); |
| 95 | void iucv_sock_link(struct iucv_sock_list *l, struct sock *s); | 95 | void iucv_sock_link(struct iucv_sock_list *l, struct sock *s); |
| 96 | void iucv_sock_unlink(struct iucv_sock_list *l, struct sock *s); | 96 | void iucv_sock_unlink(struct iucv_sock_list *l, struct sock *s); |
| 97 | int iucv_sock_wait_state(struct sock *sk, int state, int state2, | ||
| 98 | unsigned long timeo); | ||
| 99 | int iucv_sock_wait_cnt(struct sock *sk, unsigned long timeo); | 97 | int iucv_sock_wait_cnt(struct sock *sk, unsigned long timeo); |
| 100 | void iucv_accept_enqueue(struct sock *parent, struct sock *sk); | 98 | void iucv_accept_enqueue(struct sock *parent, struct sock *sk); |
| 101 | void iucv_accept_unlink(struct sock *sk); | 99 | void iucv_accept_unlink(struct sock *sk); |
diff --git a/net/ieee802154/af_ieee802154.c b/net/ieee802154/af_ieee802154.c index 882a927cefae..3bb6bdb1dac1 100644 --- a/net/ieee802154/af_ieee802154.c +++ b/net/ieee802154/af_ieee802154.c | |||
| @@ -39,14 +39,6 @@ | |||
| 39 | 39 | ||
| 40 | #include "af802154.h" | 40 | #include "af802154.h" |
| 41 | 41 | ||
| 42 | #define DBG_DUMP(data, len) { \ | ||
| 43 | int i; \ | ||
| 44 | pr_debug("function: %s: data: len %d:\n", __func__, len); \ | ||
| 45 | for (i = 0; i < len; i++) {\ | ||
| 46 | pr_debug("%02x: %02x\n", i, (data)[i]); \ | ||
| 47 | } \ | ||
| 48 | } | ||
| 49 | |||
| 50 | /* | 42 | /* |
| 51 | * Utility function for families | 43 | * Utility function for families |
| 52 | */ | 44 | */ |
| @@ -302,10 +294,12 @@ static struct net_proto_family ieee802154_family_ops = { | |||
| 302 | static int ieee802154_rcv(struct sk_buff *skb, struct net_device *dev, | 294 | static int ieee802154_rcv(struct sk_buff *skb, struct net_device *dev, |
| 303 | struct packet_type *pt, struct net_device *orig_dev) | 295 | struct packet_type *pt, struct net_device *orig_dev) |
| 304 | { | 296 | { |
| 305 | DBG_DUMP(skb->data, skb->len); | ||
| 306 | if (!netif_running(dev)) | 297 | if (!netif_running(dev)) |
| 307 | return -ENODEV; | 298 | return -ENODEV; |
| 308 | pr_debug("got frame, type %d, dev %p\n", dev->type, dev); | 299 | pr_debug("got frame, type %d, dev %p\n", dev->type, dev); |
| 300 | #ifdef DEBUG | ||
| 301 | print_hex_dump_bytes("ieee802154_rcv ", DUMP_PREFIX_NONE, skb->data, skb->len); | ||
| 302 | #endif | ||
| 309 | 303 | ||
| 310 | if (!net_eq(dev_net(dev), &init_net)) | 304 | if (!net_eq(dev_net(dev), &init_net)) |
| 311 | goto drop; | 305 | goto drop; |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index cd76b3cb7092..65b3a8b11a6c 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
| @@ -1085,8 +1085,16 @@ restart: | |||
| 1085 | now = jiffies; | 1085 | now = jiffies; |
| 1086 | 1086 | ||
| 1087 | if (!rt_caching(dev_net(rt->u.dst.dev))) { | 1087 | if (!rt_caching(dev_net(rt->u.dst.dev))) { |
| 1088 | rt_drop(rt); | 1088 | /* |
| 1089 | return 0; | 1089 | * If we're not caching, just tell the caller we |
| 1090 | * were successful and don't touch the route. The | ||
| 1091 | * caller hold the sole reference to the cache entry, and | ||
| 1092 | * it will be released when the caller is done with it. | ||
| 1093 | * If we drop it here, the callers have no way to resolve routes | ||
| 1094 | * when we're not caching. Instead, just point *rp at rt, so | ||
| 1095 | * the caller gets a single use out of the route | ||
| 1096 | */ | ||
| 1097 | goto report_and_exit; | ||
| 1090 | } | 1098 | } |
| 1091 | 1099 | ||
| 1092 | rthp = &rt_hash_table[hash].chain; | 1100 | rthp = &rt_hash_table[hash].chain; |
| @@ -1217,6 +1225,8 @@ restart: | |||
| 1217 | rcu_assign_pointer(rt_hash_table[hash].chain, rt); | 1225 | rcu_assign_pointer(rt_hash_table[hash].chain, rt); |
| 1218 | 1226 | ||
| 1219 | spin_unlock_bh(rt_hash_lock_addr(hash)); | 1227 | spin_unlock_bh(rt_hash_lock_addr(hash)); |
| 1228 | |||
| 1229 | report_and_exit: | ||
| 1220 | if (rp) | 1230 | if (rp) |
| 1221 | *rp = rt; | 1231 | *rp = rt; |
| 1222 | else | 1232 | else |
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 656cbd195825..6be5f92d1094 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c | |||
| @@ -54,6 +54,38 @@ static const u8 iprm_shutdown[8] = | |||
| 54 | #define CB_TRGCLS(skb) ((skb)->cb + CB_TAG_LEN) /* iucv msg target class */ | 54 | #define CB_TRGCLS(skb) ((skb)->cb + CB_TAG_LEN) /* iucv msg target class */ |
| 55 | #define CB_TRGCLS_LEN (TRGCLS_SIZE) | 55 | #define CB_TRGCLS_LEN (TRGCLS_SIZE) |
| 56 | 56 | ||
| 57 | #define __iucv_sock_wait(sk, condition, timeo, ret) \ | ||
| 58 | do { \ | ||
| 59 | DEFINE_WAIT(__wait); \ | ||
| 60 | long __timeo = timeo; \ | ||
| 61 | ret = 0; \ | ||
| 62 | while (!(condition)) { \ | ||
| 63 | prepare_to_wait(sk->sk_sleep, &__wait, TASK_INTERRUPTIBLE); \ | ||
| 64 | if (!__timeo) { \ | ||
| 65 | ret = -EAGAIN; \ | ||
| 66 | break; \ | ||
| 67 | } \ | ||
| 68 | if (signal_pending(current)) { \ | ||
| 69 | ret = sock_intr_errno(__timeo); \ | ||
| 70 | break; \ | ||
| 71 | } \ | ||
| 72 | release_sock(sk); \ | ||
| 73 | __timeo = schedule_timeout(__timeo); \ | ||
| 74 | lock_sock(sk); \ | ||
| 75 | ret = sock_error(sk); \ | ||
| 76 | if (ret) \ | ||
| 77 | break; \ | ||
| 78 | } \ | ||
| 79 | finish_wait(sk->sk_sleep, &__wait); \ | ||
| 80 | } while (0) | ||
| 81 | |||
| 82 | #define iucv_sock_wait(sk, condition, timeo) \ | ||
| 83 | ({ \ | ||
| 84 | int __ret = 0; \ | ||
| 85 | if (!(condition)) \ | ||
| 86 | __iucv_sock_wait(sk, condition, timeo, __ret); \ | ||
| 87 | __ret; \ | ||
| 88 | }) | ||
| 57 | 89 | ||
| 58 | static void iucv_sock_kill(struct sock *sk); | 90 | static void iucv_sock_kill(struct sock *sk); |
| 59 | static void iucv_sock_close(struct sock *sk); | 91 | static void iucv_sock_close(struct sock *sk); |
| @@ -238,6 +270,48 @@ static inline size_t iucv_msg_length(struct iucv_message *msg) | |||
| 238 | return msg->length; | 270 | return msg->length; |
| 239 | } | 271 | } |
| 240 | 272 | ||
| 273 | /** | ||
| 274 | * iucv_sock_in_state() - check for specific states | ||
| 275 | * @sk: sock structure | ||
| 276 | * @state: first iucv sk state | ||
| 277 | * @state: second iucv sk state | ||
| 278 | * | ||
| 279 | * Returns true if the socket in either in the first or second state. | ||
| 280 | */ | ||
| 281 | static int iucv_sock_in_state(struct sock *sk, int state, int state2) | ||
| 282 | { | ||
| 283 | return (sk->sk_state == state || sk->sk_state == state2); | ||
| 284 | } | ||
| 285 | |||
| 286 | /** | ||
| 287 | * iucv_below_msglim() - function to check if messages can be sent | ||
| 288 | * @sk: sock structure | ||
| 289 | * | ||
| 290 | * Returns true if the send queue length is lower than the message limit. | ||
| 291 | * Always returns true if the socket is not connected (no iucv path for | ||
| 292 | * checking the message limit). | ||
| 293 | */ | ||
| 294 | static inline int iucv_below_msglim(struct sock *sk) | ||
| 295 | { | ||
| 296 | struct iucv_sock *iucv = iucv_sk(sk); | ||
| 297 | |||
| 298 | if (sk->sk_state != IUCV_CONNECTED) | ||
| 299 | return 1; | ||
| 300 | return (skb_queue_len(&iucv->send_skb_q) < iucv->path->msglim); | ||
| 301 | } | ||
| 302 | |||
| 303 | /** | ||
| 304 | * iucv_sock_wake_msglim() - Wake up thread waiting on msg limit | ||
| 305 | */ | ||
| 306 | static void iucv_sock_wake_msglim(struct sock *sk) | ||
| 307 | { | ||
| 308 | read_lock(&sk->sk_callback_lock); | ||
| 309 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | ||
| 310 | wake_up_interruptible_all(sk->sk_sleep); | ||
| 311 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); | ||
| 312 | read_unlock(&sk->sk_callback_lock); | ||
| 313 | } | ||
| 314 | |||
| 241 | /* Timers */ | 315 | /* Timers */ |
| 242 | static void iucv_sock_timeout(unsigned long arg) | 316 | static void iucv_sock_timeout(unsigned long arg) |
| 243 | { | 317 | { |
| @@ -329,7 +403,9 @@ static void iucv_sock_close(struct sock *sk) | |||
| 329 | timeo = sk->sk_lingertime; | 403 | timeo = sk->sk_lingertime; |
| 330 | else | 404 | else |
| 331 | timeo = IUCV_DISCONN_TIMEOUT; | 405 | timeo = IUCV_DISCONN_TIMEOUT; |
| 332 | err = iucv_sock_wait_state(sk, IUCV_CLOSED, 0, timeo); | 406 | err = iucv_sock_wait(sk, |
| 407 | iucv_sock_in_state(sk, IUCV_CLOSED, 0), | ||
| 408 | timeo); | ||
| 333 | } | 409 | } |
| 334 | 410 | ||
| 335 | case IUCV_CLOSING: /* fall through */ | 411 | case IUCV_CLOSING: /* fall through */ |
| @@ -510,39 +586,6 @@ struct sock *iucv_accept_dequeue(struct sock *parent, struct socket *newsock) | |||
| 510 | return NULL; | 586 | return NULL; |
| 511 | } | 587 | } |
| 512 | 588 | ||
| 513 | int iucv_sock_wait_state(struct sock *sk, int state, int state2, | ||
| 514 | unsigned long timeo) | ||
| 515 | { | ||
| 516 | DECLARE_WAITQUEUE(wait, current); | ||
| 517 | int err = 0; | ||
| 518 | |||
| 519 | add_wait_queue(sk->sk_sleep, &wait); | ||
| 520 | while (sk->sk_state != state && sk->sk_state != state2) { | ||
| 521 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 522 | |||
| 523 | if (!timeo) { | ||
| 524 | err = -EAGAIN; | ||
| 525 | break; | ||
| 526 | } | ||
| 527 | |||
| 528 | if (signal_pending(current)) { | ||
| 529 | err = sock_intr_errno(timeo); | ||
| 530 | break; | ||
| 531 | } | ||
| 532 | |||
| 533 | release_sock(sk); | ||
| 534 | timeo = schedule_timeout(timeo); | ||
| 535 | lock_sock(sk); | ||
| 536 | |||
| 537 | err = sock_error(sk); | ||
| 538 | if (err) | ||
| 539 | break; | ||
| 540 | } | ||
| 541 | set_current_state(TASK_RUNNING); | ||
| 542 | remove_wait_queue(sk->sk_sleep, &wait); | ||
| 543 | return err; | ||
| 544 | } | ||
| 545 | |||
| 546 | /* Bind an unbound socket */ | 589 | /* Bind an unbound socket */ |
| 547 | static int iucv_sock_bind(struct socket *sock, struct sockaddr *addr, | 590 | static int iucv_sock_bind(struct socket *sock, struct sockaddr *addr, |
| 548 | int addr_len) | 591 | int addr_len) |
| @@ -687,8 +730,9 @@ static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr, | |||
| 687 | } | 730 | } |
| 688 | 731 | ||
| 689 | if (sk->sk_state != IUCV_CONNECTED) { | 732 | if (sk->sk_state != IUCV_CONNECTED) { |
| 690 | err = iucv_sock_wait_state(sk, IUCV_CONNECTED, IUCV_DISCONN, | 733 | err = iucv_sock_wait(sk, iucv_sock_in_state(sk, IUCV_CONNECTED, |
| 691 | sock_sndtimeo(sk, flags & O_NONBLOCK)); | 734 | IUCV_DISCONN), |
| 735 | sock_sndtimeo(sk, flags & O_NONBLOCK)); | ||
| 692 | } | 736 | } |
| 693 | 737 | ||
| 694 | if (sk->sk_state == IUCV_DISCONN) { | 738 | if (sk->sk_state == IUCV_DISCONN) { |
| @@ -842,9 +886,11 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
| 842 | struct iucv_message txmsg; | 886 | struct iucv_message txmsg; |
| 843 | struct cmsghdr *cmsg; | 887 | struct cmsghdr *cmsg; |
| 844 | int cmsg_done; | 888 | int cmsg_done; |
| 889 | long timeo; | ||
| 845 | char user_id[9]; | 890 | char user_id[9]; |
| 846 | char appl_id[9]; | 891 | char appl_id[9]; |
| 847 | int err; | 892 | int err; |
| 893 | int noblock = msg->msg_flags & MSG_DONTWAIT; | ||
| 848 | 894 | ||
| 849 | err = sock_error(sk); | 895 | err = sock_error(sk); |
| 850 | if (err) | 896 | if (err) |
| @@ -864,108 +910,119 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
| 864 | goto out; | 910 | goto out; |
| 865 | } | 911 | } |
| 866 | 912 | ||
| 867 | if (sk->sk_state == IUCV_CONNECTED) { | 913 | /* Return if the socket is not in connected state */ |
| 868 | /* initialize defaults */ | 914 | if (sk->sk_state != IUCV_CONNECTED) { |
| 869 | cmsg_done = 0; /* check for duplicate headers */ | 915 | err = -ENOTCONN; |
| 870 | txmsg.class = 0; | 916 | goto out; |
| 917 | } | ||
| 871 | 918 | ||
| 872 | /* iterate over control messages */ | 919 | /* initialize defaults */ |
| 873 | for (cmsg = CMSG_FIRSTHDR(msg); cmsg; | 920 | cmsg_done = 0; /* check for duplicate headers */ |
| 874 | cmsg = CMSG_NXTHDR(msg, cmsg)) { | 921 | txmsg.class = 0; |
| 875 | 922 | ||
| 876 | if (!CMSG_OK(msg, cmsg)) { | 923 | /* iterate over control messages */ |
| 877 | err = -EINVAL; | 924 | for (cmsg = CMSG_FIRSTHDR(msg); cmsg; |
| 878 | goto out; | 925 | cmsg = CMSG_NXTHDR(msg, cmsg)) { |
| 879 | } | 926 | |
| 927 | if (!CMSG_OK(msg, cmsg)) { | ||
| 928 | err = -EINVAL; | ||
| 929 | goto out; | ||
| 930 | } | ||
| 931 | |||
| 932 | if (cmsg->cmsg_level != SOL_IUCV) | ||
| 933 | continue; | ||
| 880 | 934 | ||
| 881 | if (cmsg->cmsg_level != SOL_IUCV) | 935 | if (cmsg->cmsg_type & cmsg_done) { |
| 882 | continue; | 936 | err = -EINVAL; |
| 937 | goto out; | ||
| 938 | } | ||
| 939 | cmsg_done |= cmsg->cmsg_type; | ||
| 883 | 940 | ||
| 884 | if (cmsg->cmsg_type & cmsg_done) { | 941 | switch (cmsg->cmsg_type) { |
| 942 | case SCM_IUCV_TRGCLS: | ||
| 943 | if (cmsg->cmsg_len != CMSG_LEN(TRGCLS_SIZE)) { | ||
| 885 | err = -EINVAL; | 944 | err = -EINVAL; |
| 886 | goto out; | 945 | goto out; |
| 887 | } | 946 | } |
| 888 | cmsg_done |= cmsg->cmsg_type; | ||
| 889 | |||
| 890 | switch (cmsg->cmsg_type) { | ||
| 891 | case SCM_IUCV_TRGCLS: | ||
| 892 | if (cmsg->cmsg_len != CMSG_LEN(TRGCLS_SIZE)) { | ||
| 893 | err = -EINVAL; | ||
| 894 | goto out; | ||
| 895 | } | ||
| 896 | 947 | ||
| 897 | /* set iucv message target class */ | 948 | /* set iucv message target class */ |
| 898 | memcpy(&txmsg.class, | 949 | memcpy(&txmsg.class, |
| 899 | (void *) CMSG_DATA(cmsg), TRGCLS_SIZE); | 950 | (void *) CMSG_DATA(cmsg), TRGCLS_SIZE); |
| 900 | 951 | ||
| 901 | break; | 952 | break; |
| 902 | 953 | ||
| 903 | default: | 954 | default: |
| 904 | err = -EINVAL; | 955 | err = -EINVAL; |
| 905 | goto out; | 956 | goto out; |
| 906 | break; | 957 | break; |
| 907 | } | ||
| 908 | } | 958 | } |
| 959 | } | ||
| 909 | 960 | ||
| 910 | /* allocate one skb for each iucv message: | 961 | /* allocate one skb for each iucv message: |
| 911 | * this is fine for SOCK_SEQPACKET (unless we want to support | 962 | * this is fine for SOCK_SEQPACKET (unless we want to support |
| 912 | * segmented records using the MSG_EOR flag), but | 963 | * segmented records using the MSG_EOR flag), but |
| 913 | * for SOCK_STREAM we might want to improve it in future */ | 964 | * for SOCK_STREAM we might want to improve it in future */ |
| 914 | if (!(skb = sock_alloc_send_skb(sk, len, | 965 | skb = sock_alloc_send_skb(sk, len, noblock, &err); |
| 915 | msg->msg_flags & MSG_DONTWAIT, | 966 | if (!skb) |
| 916 | &err))) | 967 | goto out; |
| 917 | goto out; | 968 | if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { |
| 969 | err = -EFAULT; | ||
| 970 | goto fail; | ||
| 971 | } | ||
| 918 | 972 | ||
| 919 | if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { | 973 | /* wait if outstanding messages for iucv path has reached */ |
| 920 | err = -EFAULT; | 974 | timeo = sock_sndtimeo(sk, noblock); |
| 921 | goto fail; | 975 | err = iucv_sock_wait(sk, iucv_below_msglim(sk), timeo); |
| 922 | } | 976 | if (err) |
| 977 | goto fail; | ||
| 923 | 978 | ||
| 924 | /* increment and save iucv message tag for msg_completion cbk */ | 979 | /* return -ECONNRESET if the socket is no longer connected */ |
| 925 | txmsg.tag = iucv->send_tag++; | 980 | if (sk->sk_state != IUCV_CONNECTED) { |
| 926 | memcpy(CB_TAG(skb), &txmsg.tag, CB_TAG_LEN); | 981 | err = -ECONNRESET; |
| 927 | skb_queue_tail(&iucv->send_skb_q, skb); | 982 | goto fail; |
| 983 | } | ||
| 928 | 984 | ||
| 929 | if (((iucv->path->flags & IUCV_IPRMDATA) & iucv->flags) | 985 | /* increment and save iucv message tag for msg_completion cbk */ |
| 930 | && skb->len <= 7) { | 986 | txmsg.tag = iucv->send_tag++; |
| 931 | err = iucv_send_iprm(iucv->path, &txmsg, skb); | 987 | memcpy(CB_TAG(skb), &txmsg.tag, CB_TAG_LEN); |
| 988 | skb_queue_tail(&iucv->send_skb_q, skb); | ||
| 932 | 989 | ||
| 933 | /* on success: there is no message_complete callback | 990 | if (((iucv->path->flags & IUCV_IPRMDATA) & iucv->flags) |
| 934 | * for an IPRMDATA msg; remove skb from send queue */ | 991 | && skb->len <= 7) { |
| 935 | if (err == 0) { | 992 | err = iucv_send_iprm(iucv->path, &txmsg, skb); |
| 936 | skb_unlink(skb, &iucv->send_skb_q); | ||
| 937 | kfree_skb(skb); | ||
| 938 | } | ||
| 939 | 993 | ||
| 940 | /* this error should never happen since the | 994 | /* on success: there is no message_complete callback |
| 941 | * IUCV_IPRMDATA path flag is set... sever path */ | 995 | * for an IPRMDATA msg; remove skb from send queue */ |
| 942 | if (err == 0x15) { | 996 | if (err == 0) { |
| 943 | iucv_path_sever(iucv->path, NULL); | 997 | skb_unlink(skb, &iucv->send_skb_q); |
| 944 | skb_unlink(skb, &iucv->send_skb_q); | 998 | kfree_skb(skb); |
| 945 | err = -EPIPE; | 999 | } |
| 946 | goto fail; | 1000 | |
| 947 | } | 1001 | /* this error should never happen since the |
| 948 | } else | 1002 | * IUCV_IPRMDATA path flag is set... sever path */ |
| 949 | err = iucv_message_send(iucv->path, &txmsg, 0, 0, | 1003 | if (err == 0x15) { |
| 950 | (void *) skb->data, skb->len); | 1004 | iucv_path_sever(iucv->path, NULL); |
| 951 | if (err) { | ||
| 952 | if (err == 3) { | ||
| 953 | user_id[8] = 0; | ||
| 954 | memcpy(user_id, iucv->dst_user_id, 8); | ||
| 955 | appl_id[8] = 0; | ||
| 956 | memcpy(appl_id, iucv->dst_name, 8); | ||
| 957 | pr_err("Application %s on z/VM guest %s" | ||
| 958 | " exceeds message limit\n", | ||
| 959 | user_id, appl_id); | ||
| 960 | } | ||
| 961 | skb_unlink(skb, &iucv->send_skb_q); | 1005 | skb_unlink(skb, &iucv->send_skb_q); |
| 962 | err = -EPIPE; | 1006 | err = -EPIPE; |
| 963 | goto fail; | 1007 | goto fail; |
| 964 | } | 1008 | } |
| 965 | 1009 | } else | |
| 966 | } else { | 1010 | err = iucv_message_send(iucv->path, &txmsg, 0, 0, |
| 967 | err = -ENOTCONN; | 1011 | (void *) skb->data, skb->len); |
| 968 | goto out; | 1012 | if (err) { |
| 1013 | if (err == 3) { | ||
| 1014 | user_id[8] = 0; | ||
| 1015 | memcpy(user_id, iucv->dst_user_id, 8); | ||
| 1016 | appl_id[8] = 0; | ||
| 1017 | memcpy(appl_id, iucv->dst_name, 8); | ||
| 1018 | pr_err("Application %s on z/VM guest %s" | ||
| 1019 | " exceeds message limit\n", | ||
| 1020 | appl_id, user_id); | ||
| 1021 | err = -EAGAIN; | ||
| 1022 | } else | ||
| 1023 | err = -EPIPE; | ||
| 1024 | skb_unlink(skb, &iucv->send_skb_q); | ||
| 1025 | goto fail; | ||
| 969 | } | 1026 | } |
| 970 | 1027 | ||
| 971 | release_sock(sk); | 1028 | release_sock(sk); |
| @@ -1581,7 +1638,11 @@ static void iucv_callback_txdone(struct iucv_path *path, | |||
| 1581 | 1638 | ||
| 1582 | spin_unlock_irqrestore(&list->lock, flags); | 1639 | spin_unlock_irqrestore(&list->lock, flags); |
| 1583 | 1640 | ||
| 1584 | kfree_skb(this); | 1641 | if (this) { |
| 1642 | kfree_skb(this); | ||
| 1643 | /* wake up any process waiting for sending */ | ||
| 1644 | iucv_sock_wake_msglim(sk); | ||
| 1645 | } | ||
| 1585 | } | 1646 | } |
| 1586 | BUG_ON(!this); | 1647 | BUG_ON(!this); |
| 1587 | 1648 | ||
diff --git a/net/rfkill/core.c b/net/rfkill/core.c index 4e68ab439d5d..79693fe2001e 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c | |||
| @@ -56,7 +56,6 @@ struct rfkill { | |||
| 56 | u32 idx; | 56 | u32 idx; |
| 57 | 57 | ||
| 58 | bool registered; | 58 | bool registered; |
| 59 | bool suspended; | ||
| 60 | bool persistent; | 59 | bool persistent; |
| 61 | 60 | ||
| 62 | const struct rfkill_ops *ops; | 61 | const struct rfkill_ops *ops; |
| @@ -224,7 +223,7 @@ static void rfkill_send_events(struct rfkill *rfkill, enum rfkill_operation op) | |||
| 224 | 223 | ||
| 225 | static void rfkill_event(struct rfkill *rfkill) | 224 | static void rfkill_event(struct rfkill *rfkill) |
| 226 | { | 225 | { |
| 227 | if (!rfkill->registered || rfkill->suspended) | 226 | if (!rfkill->registered) |
| 228 | return; | 227 | return; |
| 229 | 228 | ||
| 230 | kobject_uevent(&rfkill->dev.kobj, KOBJ_CHANGE); | 229 | kobject_uevent(&rfkill->dev.kobj, KOBJ_CHANGE); |
| @@ -270,6 +269,9 @@ static void rfkill_set_block(struct rfkill *rfkill, bool blocked) | |||
| 270 | unsigned long flags; | 269 | unsigned long flags; |
| 271 | int err; | 270 | int err; |
| 272 | 271 | ||
| 272 | if (unlikely(rfkill->dev.power.power_state.event & PM_EVENT_SLEEP)) | ||
| 273 | return; | ||
| 274 | |||
| 273 | /* | 275 | /* |
| 274 | * Some platforms (...!) generate input events which affect the | 276 | * Some platforms (...!) generate input events which affect the |
| 275 | * _hard_ kill state -- whenever something tries to change the | 277 | * _hard_ kill state -- whenever something tries to change the |
| @@ -292,9 +294,6 @@ static void rfkill_set_block(struct rfkill *rfkill, bool blocked) | |||
| 292 | rfkill->state |= RFKILL_BLOCK_SW_SETCALL; | 294 | rfkill->state |= RFKILL_BLOCK_SW_SETCALL; |
| 293 | spin_unlock_irqrestore(&rfkill->lock, flags); | 295 | spin_unlock_irqrestore(&rfkill->lock, flags); |
| 294 | 296 | ||
| 295 | if (unlikely(rfkill->dev.power.power_state.event & PM_EVENT_SLEEP)) | ||
| 296 | return; | ||
| 297 | |||
| 298 | err = rfkill->ops->set_block(rfkill->data, blocked); | 297 | err = rfkill->ops->set_block(rfkill->data, blocked); |
| 299 | 298 | ||
| 300 | spin_lock_irqsave(&rfkill->lock, flags); | 299 | spin_lock_irqsave(&rfkill->lock, flags); |
| @@ -508,19 +507,32 @@ bool rfkill_set_sw_state(struct rfkill *rfkill, bool blocked) | |||
| 508 | blocked = blocked || hwblock; | 507 | blocked = blocked || hwblock; |
| 509 | spin_unlock_irqrestore(&rfkill->lock, flags); | 508 | spin_unlock_irqrestore(&rfkill->lock, flags); |
| 510 | 509 | ||
| 511 | if (!rfkill->registered) { | 510 | if (!rfkill->registered) |
| 512 | rfkill->persistent = true; | 511 | return blocked; |
| 513 | } else { | ||
| 514 | if (prev != blocked && !hwblock) | ||
| 515 | schedule_work(&rfkill->uevent_work); | ||
| 516 | 512 | ||
| 517 | rfkill_led_trigger_event(rfkill); | 513 | if (prev != blocked && !hwblock) |
| 518 | } | 514 | schedule_work(&rfkill->uevent_work); |
| 515 | |||
| 516 | rfkill_led_trigger_event(rfkill); | ||
| 519 | 517 | ||
| 520 | return blocked; | 518 | return blocked; |
| 521 | } | 519 | } |
| 522 | EXPORT_SYMBOL(rfkill_set_sw_state); | 520 | EXPORT_SYMBOL(rfkill_set_sw_state); |
| 523 | 521 | ||
| 522 | void rfkill_init_sw_state(struct rfkill *rfkill, bool blocked) | ||
| 523 | { | ||
| 524 | unsigned long flags; | ||
| 525 | |||
| 526 | BUG_ON(!rfkill); | ||
| 527 | BUG_ON(rfkill->registered); | ||
| 528 | |||
| 529 | spin_lock_irqsave(&rfkill->lock, flags); | ||
| 530 | __rfkill_set_sw_state(rfkill, blocked); | ||
| 531 | rfkill->persistent = true; | ||
| 532 | spin_unlock_irqrestore(&rfkill->lock, flags); | ||
| 533 | } | ||
| 534 | EXPORT_SYMBOL(rfkill_init_sw_state); | ||
| 535 | |||
| 524 | void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw) | 536 | void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw) |
| 525 | { | 537 | { |
| 526 | unsigned long flags; | 538 | unsigned long flags; |
| @@ -598,6 +610,15 @@ static ssize_t rfkill_idx_show(struct device *dev, | |||
| 598 | return sprintf(buf, "%d\n", rfkill->idx); | 610 | return sprintf(buf, "%d\n", rfkill->idx); |
| 599 | } | 611 | } |
| 600 | 612 | ||
| 613 | static ssize_t rfkill_persistent_show(struct device *dev, | ||
| 614 | struct device_attribute *attr, | ||
| 615 | char *buf) | ||
| 616 | { | ||
| 617 | struct rfkill *rfkill = to_rfkill(dev); | ||
| 618 | |||
| 619 | return sprintf(buf, "%d\n", rfkill->persistent); | ||
| 620 | } | ||
| 621 | |||
| 601 | static u8 user_state_from_blocked(unsigned long state) | 622 | static u8 user_state_from_blocked(unsigned long state) |
| 602 | { | 623 | { |
| 603 | if (state & RFKILL_BLOCK_HW) | 624 | if (state & RFKILL_BLOCK_HW) |
| @@ -656,6 +677,7 @@ static struct device_attribute rfkill_dev_attrs[] = { | |||
| 656 | __ATTR(name, S_IRUGO, rfkill_name_show, NULL), | 677 | __ATTR(name, S_IRUGO, rfkill_name_show, NULL), |
| 657 | __ATTR(type, S_IRUGO, rfkill_type_show, NULL), | 678 | __ATTR(type, S_IRUGO, rfkill_type_show, NULL), |
| 658 | __ATTR(index, S_IRUGO, rfkill_idx_show, NULL), | 679 | __ATTR(index, S_IRUGO, rfkill_idx_show, NULL), |
| 680 | __ATTR(persistent, S_IRUGO, rfkill_persistent_show, NULL), | ||
| 659 | __ATTR(state, S_IRUGO|S_IWUSR, rfkill_state_show, rfkill_state_store), | 681 | __ATTR(state, S_IRUGO|S_IWUSR, rfkill_state_show, rfkill_state_store), |
| 660 | __ATTR(claim, S_IRUGO|S_IWUSR, rfkill_claim_show, rfkill_claim_store), | 682 | __ATTR(claim, S_IRUGO|S_IWUSR, rfkill_claim_show, rfkill_claim_store), |
| 661 | __ATTR_NULL | 683 | __ATTR_NULL |
| @@ -718,8 +740,6 @@ static int rfkill_suspend(struct device *dev, pm_message_t state) | |||
| 718 | 740 | ||
| 719 | rfkill_pause_polling(rfkill); | 741 | rfkill_pause_polling(rfkill); |
| 720 | 742 | ||
| 721 | rfkill->suspended = true; | ||
| 722 | |||
| 723 | return 0; | 743 | return 0; |
| 724 | } | 744 | } |
| 725 | 745 | ||
| @@ -728,10 +748,10 @@ static int rfkill_resume(struct device *dev) | |||
| 728 | struct rfkill *rfkill = to_rfkill(dev); | 748 | struct rfkill *rfkill = to_rfkill(dev); |
| 729 | bool cur; | 749 | bool cur; |
| 730 | 750 | ||
| 731 | cur = !!(rfkill->state & RFKILL_BLOCK_SW); | 751 | if (!rfkill->persistent) { |
| 732 | rfkill_set_block(rfkill, cur); | 752 | cur = !!(rfkill->state & RFKILL_BLOCK_SW); |
| 733 | 753 | rfkill_set_block(rfkill, cur); | |
| 734 | rfkill->suspended = false; | 754 | } |
| 735 | 755 | ||
| 736 | rfkill_resume_polling(rfkill); | 756 | rfkill_resume_polling(rfkill); |
| 737 | 757 | ||
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 24168560ebae..241bddd0b4f1 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
| @@ -1687,13 +1687,52 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
| 1687 | if (err) | 1687 | if (err) |
| 1688 | goto out_rtnl; | 1688 | goto out_rtnl; |
| 1689 | 1689 | ||
| 1690 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | 1690 | err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan); |
| 1691 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) { | 1691 | if (err) |
| 1692 | err = -EINVAL; | ||
| 1693 | goto out; | 1692 | goto out; |
| 1693 | |||
| 1694 | /* validate settings */ | ||
| 1695 | err = 0; | ||
| 1696 | |||
| 1697 | switch (dev->ieee80211_ptr->iftype) { | ||
| 1698 | case NL80211_IFTYPE_AP: | ||
| 1699 | case NL80211_IFTYPE_AP_VLAN: | ||
| 1700 | /* disallow mesh-specific things */ | ||
| 1701 | if (params.plink_action) | ||
| 1702 | err = -EINVAL; | ||
| 1703 | break; | ||
| 1704 | case NL80211_IFTYPE_STATION: | ||
| 1705 | /* disallow everything but AUTHORIZED flag */ | ||
| 1706 | if (params.plink_action) | ||
| 1707 | err = -EINVAL; | ||
| 1708 | if (params.vlan) | ||
| 1709 | err = -EINVAL; | ||
| 1710 | if (params.supported_rates) | ||
| 1711 | err = -EINVAL; | ||
| 1712 | if (params.ht_capa) | ||
| 1713 | err = -EINVAL; | ||
| 1714 | if (params.listen_interval >= 0) | ||
| 1715 | err = -EINVAL; | ||
| 1716 | if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED)) | ||
| 1717 | err = -EINVAL; | ||
| 1718 | break; | ||
| 1719 | case NL80211_IFTYPE_MESH_POINT: | ||
| 1720 | /* disallow things mesh doesn't support */ | ||
| 1721 | if (params.vlan) | ||
| 1722 | err = -EINVAL; | ||
| 1723 | if (params.ht_capa) | ||
| 1724 | err = -EINVAL; | ||
| 1725 | if (params.listen_interval >= 0) | ||
| 1726 | err = -EINVAL; | ||
| 1727 | if (params.supported_rates) | ||
| 1728 | err = -EINVAL; | ||
| 1729 | if (params.sta_flags_mask) | ||
| 1730 | err = -EINVAL; | ||
| 1731 | break; | ||
| 1732 | default: | ||
| 1733 | err = -EINVAL; | ||
| 1694 | } | 1734 | } |
| 1695 | 1735 | ||
| 1696 | err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan); | ||
| 1697 | if (err) | 1736 | if (err) |
| 1698 | goto out; | 1737 | goto out; |
| 1699 | 1738 | ||
| @@ -1728,9 +1767,6 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
| 1728 | if (!info->attrs[NL80211_ATTR_MAC]) | 1767 | if (!info->attrs[NL80211_ATTR_MAC]) |
| 1729 | return -EINVAL; | 1768 | return -EINVAL; |
| 1730 | 1769 | ||
| 1731 | if (!info->attrs[NL80211_ATTR_STA_AID]) | ||
| 1732 | return -EINVAL; | ||
| 1733 | |||
| 1734 | if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]) | 1770 | if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]) |
| 1735 | return -EINVAL; | 1771 | return -EINVAL; |
| 1736 | 1772 | ||
| @@ -1745,9 +1781,11 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
| 1745 | params.listen_interval = | 1781 | params.listen_interval = |
| 1746 | nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); | 1782 | nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); |
| 1747 | 1783 | ||
| 1748 | params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); | 1784 | if (info->attrs[NL80211_ATTR_STA_AID]) { |
| 1749 | if (!params.aid || params.aid > IEEE80211_MAX_AID) | 1785 | params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); |
| 1750 | return -EINVAL; | 1786 | if (!params.aid || params.aid > IEEE80211_MAX_AID) |
| 1787 | return -EINVAL; | ||
| 1788 | } | ||
| 1751 | 1789 | ||
| 1752 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) | 1790 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) |
| 1753 | params.ht_capa = | 1791 | params.ht_capa = |
| @@ -1762,13 +1800,39 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
| 1762 | if (err) | 1800 | if (err) |
| 1763 | goto out_rtnl; | 1801 | goto out_rtnl; |
| 1764 | 1802 | ||
| 1765 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | 1803 | err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan); |
| 1766 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) { | 1804 | if (err) |
| 1767 | err = -EINVAL; | ||
| 1768 | goto out; | 1805 | goto out; |
| 1806 | |||
| 1807 | /* validate settings */ | ||
| 1808 | err = 0; | ||
| 1809 | |||
| 1810 | switch (dev->ieee80211_ptr->iftype) { | ||
| 1811 | case NL80211_IFTYPE_AP: | ||
| 1812 | case NL80211_IFTYPE_AP_VLAN: | ||
| 1813 | /* all ok but must have AID */ | ||
| 1814 | if (!params.aid) | ||
| 1815 | err = -EINVAL; | ||
| 1816 | break; | ||
| 1817 | case NL80211_IFTYPE_MESH_POINT: | ||
| 1818 | /* disallow things mesh doesn't support */ | ||
| 1819 | if (params.vlan) | ||
| 1820 | err = -EINVAL; | ||
| 1821 | if (params.aid) | ||
| 1822 | err = -EINVAL; | ||
| 1823 | if (params.ht_capa) | ||
| 1824 | err = -EINVAL; | ||
| 1825 | if (params.listen_interval >= 0) | ||
| 1826 | err = -EINVAL; | ||
| 1827 | if (params.supported_rates) | ||
| 1828 | err = -EINVAL; | ||
| 1829 | if (params.sta_flags_mask) | ||
| 1830 | err = -EINVAL; | ||
| 1831 | break; | ||
| 1832 | default: | ||
| 1833 | err = -EINVAL; | ||
| 1769 | } | 1834 | } |
| 1770 | 1835 | ||
| 1771 | err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan); | ||
| 1772 | if (err) | 1836 | if (err) |
| 1773 | goto out; | 1837 | goto out; |
| 1774 | 1838 | ||
| @@ -1812,7 +1876,8 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info) | |||
| 1812 | goto out_rtnl; | 1876 | goto out_rtnl; |
| 1813 | 1877 | ||
| 1814 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | 1878 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
| 1815 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) { | 1879 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && |
| 1880 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) { | ||
| 1816 | err = -EINVAL; | 1881 | err = -EINVAL; |
| 1817 | goto out; | 1882 | goto out; |
| 1818 | } | 1883 | } |
