Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fjes: net_device_ops.ndo_open and .ndo_stop

This patch adds net_device_ops.ndo_open and .ndo_stop
callback. These function is called when network device
activation and deactivation.

Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Taku Izumi and committed by
David S. Miller
e5d486dc 7950e6c5

+439
+1
drivers/net/fjes/fjes.h
··· 29 29 #define FJES_ACPI_SYMBOL "Extended Socket" 30 30 #define FJES_MAX_QUEUES 1 31 31 #define FJES_TX_RETRY_INTERVAL (20 * HZ) 32 + #define FJES_OPEN_ZONE_UPDATE_WAIT (300) /* msec */ 32 33 33 34 /* board specific private data structure */ 34 35 struct fjes_adapter {
+145
drivers/net/fjes/fjes_hw.c
··· 638 638 return result; 639 639 } 640 640 641 + int fjes_hw_raise_interrupt(struct fjes_hw *hw, int dest_epid, 642 + enum REG_ICTL_MASK mask) 643 + { 644 + u32 ig = mask | dest_epid; 645 + 646 + wr32(XSCT_IG, cpu_to_le32(ig)); 647 + 648 + return 0; 649 + } 650 + 651 + u32 fjes_hw_capture_interrupt_status(struct fjes_hw *hw) 652 + { 653 + u32 cur_is; 654 + 655 + cur_is = rd32(XSCT_IS); 656 + 657 + return cur_is; 658 + } 659 + 641 660 void fjes_hw_set_irqmask(struct fjes_hw *hw, 642 661 enum REG_ICTL_MASK intr_mask, bool mask) 643 662 { ··· 664 645 wr32(XSCT_IMS, intr_mask); 665 646 else 666 647 wr32(XSCT_IMC, intr_mask); 648 + } 649 + 650 + bool fjes_hw_epid_is_same_zone(struct fjes_hw *hw, int epid) 651 + { 652 + if (epid >= hw->max_epid) 653 + return false; 654 + 655 + if ((hw->ep_shm_info[epid].es_status != 656 + FJES_ZONING_STATUS_ENABLE) || 657 + (hw->ep_shm_info[hw->my_epid].zone == 658 + FJES_ZONING_ZONE_TYPE_NONE)) 659 + return false; 660 + else 661 + return (hw->ep_shm_info[epid].zone == 662 + hw->ep_shm_info[hw->my_epid].zone); 663 + } 664 + 665 + int fjes_hw_epid_is_shared(struct fjes_device_shared_info *share, 666 + int dest_epid) 667 + { 668 + int value = false; 669 + 670 + if (dest_epid < share->epnum) 671 + value = share->ep_status[dest_epid]; 672 + 673 + return value; 674 + } 675 + 676 + static bool fjes_hw_epid_is_stop_requested(struct fjes_hw *hw, int src_epid) 677 + { 678 + return test_bit(src_epid, &hw->txrx_stop_req_bit); 679 + } 680 + 681 + static bool fjes_hw_epid_is_stop_process_done(struct fjes_hw *hw, int src_epid) 682 + { 683 + return (hw->ep_shm_info[src_epid].tx.info->v1i.rx_status & 684 + FJES_RX_STOP_REQ_DONE); 685 + } 686 + 687 + enum ep_partner_status 688 + fjes_hw_get_partner_ep_status(struct fjes_hw *hw, int epid) 689 + { 690 + enum ep_partner_status status; 691 + 692 + if (fjes_hw_epid_is_shared(hw->hw_info.share, epid)) { 693 + if (fjes_hw_epid_is_stop_requested(hw, epid)) { 694 + status = EP_PARTNER_WAITING; 695 + } else { 696 + if (fjes_hw_epid_is_stop_process_done(hw, epid)) 697 + status = EP_PARTNER_COMPLETE; 698 + else 699 + status = EP_PARTNER_SHARED; 700 + } 701 + } else { 702 + status = EP_PARTNER_UNSHARE; 703 + } 704 + 705 + return status; 706 + } 707 + 708 + void fjes_hw_raise_epstop(struct fjes_hw *hw) 709 + { 710 + enum ep_partner_status status; 711 + int epidx; 712 + 713 + for (epidx = 0; epidx < hw->max_epid; epidx++) { 714 + if (epidx == hw->my_epid) 715 + continue; 716 + 717 + status = fjes_hw_get_partner_ep_status(hw, epidx); 718 + switch (status) { 719 + case EP_PARTNER_SHARED: 720 + fjes_hw_raise_interrupt(hw, epidx, 721 + REG_ICTL_MASK_TXRX_STOP_REQ); 722 + break; 723 + default: 724 + break; 725 + } 726 + 727 + set_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit); 728 + set_bit(epidx, &hw->txrx_stop_req_bit); 729 + 730 + hw->ep_shm_info[epidx].tx.info->v1i.rx_status |= 731 + FJES_RX_STOP_REQ_REQUEST; 732 + } 733 + } 734 + 735 + int fjes_hw_wait_epstop(struct fjes_hw *hw) 736 + { 737 + enum ep_partner_status status; 738 + union ep_buffer_info *info; 739 + int wait_time = 0; 740 + int epidx; 741 + 742 + while (hw->hw_info.buffer_unshare_reserve_bit && 743 + (wait_time < FJES_COMMAND_EPSTOP_WAIT_TIMEOUT * 1000)) { 744 + for (epidx = 0; epidx < hw->max_epid; epidx++) { 745 + if (epidx == hw->my_epid) 746 + continue; 747 + status = fjes_hw_epid_is_shared(hw->hw_info.share, 748 + epidx); 749 + info = hw->ep_shm_info[epidx].rx.info; 750 + if ((!status || 751 + (info->v1i.rx_status & 752 + FJES_RX_STOP_REQ_DONE)) && 753 + test_bit(epidx, 754 + &hw->hw_info.buffer_unshare_reserve_bit)) { 755 + clear_bit(epidx, 756 + &hw->hw_info.buffer_unshare_reserve_bit); 757 + } 758 + } 759 + 760 + msleep(100); 761 + wait_time += 100; 762 + } 763 + 764 + for (epidx = 0; epidx < hw->max_epid; epidx++) { 765 + if (epidx == hw->my_epid) 766 + continue; 767 + if (test_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit)) 768 + clear_bit(epidx, 769 + &hw->hw_info.buffer_unshare_reserve_bit); 770 + } 771 + 772 + return (wait_time < FJES_COMMAND_EPSTOP_WAIT_TIMEOUT * 1000) 773 + ? 0 : -EBUSY; 667 774 }
+30
drivers/net/fjes/fjes_hw.h
··· 36 36 #define FJES_DEVICE_RESET_TIMEOUT ((17 + 1) * 3) /* sec */ 37 37 #define FJES_COMMAND_REQ_TIMEOUT (5 + 1) /* sec */ 38 38 #define FJES_COMMAND_REQ_BUFF_TIMEOUT (8 * 3) /* sec */ 39 + #define FJES_COMMAND_EPSTOP_WAIT_TIMEOUT (1) /* sec */ 39 40 40 41 #define FJES_CMD_REQ_ERR_INFO_PARAM (0x0001) 41 42 #define FJES_CMD_REQ_ERR_INFO_STATUS (0x0002) 42 43 43 44 #define FJES_CMD_REQ_RES_CODE_NORMAL (0) 44 45 #define FJES_CMD_REQ_RES_CODE_BUSY (1) 46 + 47 + #define FJES_ZONING_STATUS_DISABLE (0x00) 48 + #define FJES_ZONING_STATUS_ENABLE (0x01) 49 + #define FJES_ZONING_STATUS_INVALID (0xFF) 50 + 51 + #define FJES_ZONING_ZONE_TYPE_NONE (0xFF) 52 + 53 + #define FJES_RX_STOP_REQ_NONE (0x0) 54 + #define FJES_RX_STOP_REQ_DONE (0x1) 55 + #define FJES_RX_STOP_REQ_REQUEST (0x2) 56 + #define FJES_RX_POLL_WORK (0x4) 45 57 46 58 #define EP_BUFFER_SIZE \ 47 59 (((sizeof(union ep_buffer_info) + (128 * (64 * 1024))) \ ··· 87 75 struct esmem_frame { 88 76 __le32 frame_size; 89 77 u8 frame_data[]; 78 + }; 79 + 80 + /* EP partner status */ 81 + enum ep_partner_status { 82 + EP_PARTNER_UNSHARE, 83 + EP_PARTNER_SHARED, 84 + EP_PARTNER_WAITING, 85 + EP_PARTNER_COMPLETE, 86 + EP_PARTNER_STATUS_MAX, 90 87 }; 91 88 92 89 /* shared status region */ ··· 299 278 void fjes_hw_init_command_registers(struct fjes_hw *, 300 279 struct fjes_device_command_param *); 301 280 void fjes_hw_setup_epbuf(struct epbuf_handler *, u8 *, u32); 281 + int fjes_hw_raise_interrupt(struct fjes_hw *, int, enum REG_ICTL_MASK); 302 282 void fjes_hw_set_irqmask(struct fjes_hw *, enum REG_ICTL_MASK, bool); 283 + u32 fjes_hw_capture_interrupt_status(struct fjes_hw *); 284 + void fjes_hw_raise_epstop(struct fjes_hw *); 285 + int fjes_hw_wait_epstop(struct fjes_hw *); 286 + enum ep_partner_status 287 + fjes_hw_get_partner_ep_status(struct fjes_hw *, int); 288 + 289 + bool fjes_hw_epid_is_same_zone(struct fjes_hw *, int); 290 + int fjes_hw_epid_is_shared(struct fjes_device_shared_info *, int); 303 291 304 292 #endif /* FJES_HW_H_ */
+246
drivers/net/fjes/fjes_main.c
··· 24 24 #include <linux/nls.h> 25 25 #include <linux/platform_device.h> 26 26 #include <linux/netdevice.h> 27 + #include <linux/interrupt.h> 27 28 28 29 #include "fjes.h" 29 30 ··· 43 42 MODULE_DESCRIPTION("FUJITSU Extended Socket Network Device Driver"); 44 43 MODULE_LICENSE("GPL"); 45 44 MODULE_VERSION(DRV_VERSION); 45 + 46 + static int fjes_request_irq(struct fjes_adapter *); 47 + static void fjes_free_irq(struct fjes_adapter *); 48 + 49 + static int fjes_open(struct net_device *); 50 + static int fjes_close(struct net_device *); 51 + static int fjes_setup_resources(struct fjes_adapter *); 52 + static void fjes_free_resources(struct fjes_adapter *); 53 + static irqreturn_t fjes_intr(int, void*); 46 54 47 55 static int fjes_acpi_add(struct acpi_device *); 48 56 static int fjes_acpi_remove(struct acpi_device *); ··· 180 170 return AE_OK; 181 171 } 182 172 173 + static int fjes_request_irq(struct fjes_adapter *adapter) 174 + { 175 + struct net_device *netdev = adapter->netdev; 176 + int result = -1; 177 + 178 + if (!adapter->irq_registered) { 179 + result = request_irq(adapter->hw.hw_res.irq, fjes_intr, 180 + IRQF_SHARED, netdev->name, adapter); 181 + if (result) 182 + adapter->irq_registered = false; 183 + else 184 + adapter->irq_registered = true; 185 + } 186 + 187 + return result; 188 + } 189 + 190 + static void fjes_free_irq(struct fjes_adapter *adapter) 191 + { 192 + struct fjes_hw *hw = &adapter->hw; 193 + 194 + fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, true); 195 + 196 + if (adapter->irq_registered) { 197 + free_irq(adapter->hw.hw_res.irq, adapter); 198 + adapter->irq_registered = false; 199 + } 200 + } 201 + 183 202 static const struct net_device_ops fjes_netdev_ops = { 203 + .ndo_open = fjes_open, 204 + .ndo_stop = fjes_close, 184 205 }; 206 + 207 + /* fjes_open - Called when a network interface is made active */ 208 + static int fjes_open(struct net_device *netdev) 209 + { 210 + struct fjes_adapter *adapter = netdev_priv(netdev); 211 + struct fjes_hw *hw = &adapter->hw; 212 + int result; 213 + 214 + if (adapter->open_guard) 215 + return -ENXIO; 216 + 217 + result = fjes_setup_resources(adapter); 218 + if (result) 219 + goto err_setup_res; 220 + 221 + hw->txrx_stop_req_bit = 0; 222 + hw->epstop_req_bit = 0; 223 + 224 + fjes_hw_capture_interrupt_status(hw); 225 + 226 + result = fjes_request_irq(adapter); 227 + if (result) 228 + goto err_req_irq; 229 + 230 + fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, false); 231 + 232 + netif_tx_start_all_queues(netdev); 233 + netif_carrier_on(netdev); 234 + 235 + return 0; 236 + 237 + err_req_irq: 238 + fjes_free_irq(adapter); 239 + 240 + err_setup_res: 241 + fjes_free_resources(adapter); 242 + return result; 243 + } 244 + 245 + /* fjes_close - Disables a network interface */ 246 + static int fjes_close(struct net_device *netdev) 247 + { 248 + struct fjes_adapter *adapter = netdev_priv(netdev); 249 + struct fjes_hw *hw = &adapter->hw; 250 + int epidx; 251 + 252 + netif_tx_stop_all_queues(netdev); 253 + netif_carrier_off(netdev); 254 + 255 + fjes_hw_raise_epstop(hw); 256 + 257 + for (epidx = 0; epidx < hw->max_epid; epidx++) { 258 + if (epidx == hw->my_epid) 259 + continue; 260 + 261 + adapter->hw.ep_shm_info[epidx].tx.info->v1i.rx_status &= 262 + ~FJES_RX_POLL_WORK; 263 + } 264 + 265 + fjes_free_irq(adapter); 266 + 267 + fjes_hw_wait_epstop(hw); 268 + 269 + fjes_free_resources(adapter); 270 + 271 + return 0; 272 + } 273 + 274 + static int fjes_setup_resources(struct fjes_adapter *adapter) 275 + { 276 + struct net_device *netdev = adapter->netdev; 277 + struct ep_share_mem_info *buf_pair; 278 + struct fjes_hw *hw = &adapter->hw; 279 + int result; 280 + int epidx; 281 + 282 + mutex_lock(&hw->hw_info.lock); 283 + result = fjes_hw_request_info(hw); 284 + switch (result) { 285 + case 0: 286 + for (epidx = 0; epidx < hw->max_epid; epidx++) { 287 + hw->ep_shm_info[epidx].es_status = 288 + hw->hw_info.res_buf->info.info[epidx].es_status; 289 + hw->ep_shm_info[epidx].zone = 290 + hw->hw_info.res_buf->info.info[epidx].zone; 291 + } 292 + break; 293 + default: 294 + case -ENOMSG: 295 + case -EBUSY: 296 + adapter->force_reset = true; 297 + 298 + mutex_unlock(&hw->hw_info.lock); 299 + return result; 300 + } 301 + mutex_unlock(&hw->hw_info.lock); 302 + 303 + for (epidx = 0; epidx < (hw->max_epid); epidx++) { 304 + if ((epidx != hw->my_epid) && 305 + (hw->ep_shm_info[epidx].es_status == 306 + FJES_ZONING_STATUS_ENABLE)) { 307 + fjes_hw_raise_interrupt(hw, epidx, 308 + REG_ICTL_MASK_INFO_UPDATE); 309 + } 310 + } 311 + 312 + msleep(FJES_OPEN_ZONE_UPDATE_WAIT * hw->max_epid); 313 + 314 + for (epidx = 0; epidx < (hw->max_epid); epidx++) { 315 + if (epidx == hw->my_epid) 316 + continue; 317 + 318 + buf_pair = &hw->ep_shm_info[epidx]; 319 + 320 + fjes_hw_setup_epbuf(&buf_pair->tx, netdev->dev_addr, 321 + netdev->mtu); 322 + 323 + if (fjes_hw_epid_is_same_zone(hw, epidx)) { 324 + mutex_lock(&hw->hw_info.lock); 325 + result = 326 + fjes_hw_register_buff_addr(hw, epidx, buf_pair); 327 + mutex_unlock(&hw->hw_info.lock); 328 + 329 + switch (result) { 330 + case 0: 331 + break; 332 + case -ENOMSG: 333 + case -EBUSY: 334 + default: 335 + adapter->force_reset = true; 336 + return result; 337 + } 338 + } 339 + } 340 + 341 + return 0; 342 + } 343 + 344 + static void fjes_free_resources(struct fjes_adapter *adapter) 345 + { 346 + struct net_device *netdev = adapter->netdev; 347 + struct fjes_device_command_param param; 348 + struct ep_share_mem_info *buf_pair; 349 + struct fjes_hw *hw = &adapter->hw; 350 + bool reset_flag = false; 351 + int result; 352 + int epidx; 353 + 354 + for (epidx = 0; epidx < hw->max_epid; epidx++) { 355 + if (epidx == hw->my_epid) 356 + continue; 357 + 358 + mutex_lock(&hw->hw_info.lock); 359 + result = fjes_hw_unregister_buff_addr(hw, epidx); 360 + mutex_unlock(&hw->hw_info.lock); 361 + 362 + if (result) 363 + reset_flag = true; 364 + 365 + buf_pair = &hw->ep_shm_info[epidx]; 366 + 367 + fjes_hw_setup_epbuf(&buf_pair->tx, 368 + netdev->dev_addr, netdev->mtu); 369 + 370 + clear_bit(epidx, &hw->txrx_stop_req_bit); 371 + } 372 + 373 + if (reset_flag || adapter->force_reset) { 374 + result = fjes_hw_reset(hw); 375 + 376 + adapter->force_reset = false; 377 + 378 + if (result) 379 + adapter->open_guard = true; 380 + 381 + hw->hw_info.buffer_share_bit = 0; 382 + 383 + memset((void *)&param, 0, sizeof(param)); 384 + 385 + param.req_len = hw->hw_info.req_buf_size; 386 + param.req_start = __pa(hw->hw_info.req_buf); 387 + param.res_len = hw->hw_info.res_buf_size; 388 + param.res_start = __pa(hw->hw_info.res_buf); 389 + param.share_start = __pa(hw->hw_info.share->ep_status); 390 + 391 + fjes_hw_init_command_registers(hw, &param); 392 + } 393 + } 394 + 395 + static irqreturn_t fjes_intr(int irq, void *data) 396 + { 397 + struct fjes_adapter *adapter = data; 398 + struct fjes_hw *hw = &adapter->hw; 399 + irqreturn_t ret; 400 + u32 icr; 401 + 402 + icr = fjes_hw_capture_interrupt_status(hw); 403 + 404 + if (icr & REG_IS_MASK_IS_ASSERT) 405 + ret = IRQ_HANDLED; 406 + else 407 + ret = IRQ_NONE; 408 + 409 + return ret; 410 + } 185 411 186 412 /* fjes_probe - Device Initialization Routine */ 187 413 static int fjes_probe(struct platform_device *plat_dev)
+17
drivers/net/fjes/fjes_regs.h
··· 49 49 #define XSCT_RESPBAH 0x004C /* Response Buffer Address High */ 50 50 51 51 /* Interrupt Control registers */ 52 + #define XSCT_IS 0x0080 /* Interrupt status */ 52 53 #define XSCT_IMS 0x0084 /* Interrupt mask set */ 53 54 #define XSCT_IMC 0x0088 /* Interrupt mask clear */ 55 + #define XSCT_IG 0x008C /* Interrupt generator */ 56 + #define XSCT_ICTL 0x0090 /* Interrupt control */ 54 57 55 58 /* register structure */ 56 59 /* Information registers */ ··· 104 101 __le32 reg; 105 102 }; 106 103 104 + /* Interrupt Control registers */ 105 + union REG_ICTL { 106 + struct { 107 + __le32 automak:1; 108 + __le32 rsv0:31; 109 + } bits; 110 + __le32 reg; 111 + }; 112 + 107 113 enum REG_ICTL_MASK { 108 114 REG_ICTL_MASK_INFO_UPDATE = 1 << 20, 109 115 REG_ICTL_MASK_DEV_STOP_REQ = 1 << 19, ··· 120 108 REG_ICTL_MASK_TXRX_STOP_DONE = 1 << 17, 121 109 REG_ICTL_MASK_RX_DATA = 1 << 16, 122 110 REG_ICTL_MASK_ALL = GENMASK(20, 16), 111 + }; 112 + 113 + enum REG_IS_MASK { 114 + REG_IS_MASK_IS_ASSERT = 1 << 31, 115 + REG_IS_MASK_EPID = GENMASK(15, 0), 123 116 }; 124 117 125 118 struct fjes_hw;