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

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'net-ipa-small-transaction-updates'

Alex Elder says:

====================
net: ipa: small transaction updates

Version 2 of this series corrects a misspelling of "outstanding"
pointed out by the netdev test bots. (For some reason I don't see
that when I run "checkpatch".) I found and fixed a second instance
of that word being misspelled as well.

This series includes three changes to the transaction code. The
first adds a new transaction list that represents a distinct state
that has not been maintained. The second moves a field in the
transaction information structure, and reorders its initialization
a bit. The third skips a function call when it is known not to be
necessary.

The last two are very small "leftover" patches.
====================

Link: https://lore.kernel.org/r/20220719181020.372697-1-elder@linaro.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+67 -39
+4 -1
drivers/net/ipa/gsi.c
··· 722 722 list = &trans_info->alloc; 723 723 if (!list_empty(list)) 724 724 goto done; 725 + list = &trans_info->committed; 726 + if (!list_empty(list)) 727 + goto done; 725 728 list = &trans_info->pending; 726 729 if (!list_empty(list)) 727 730 goto done; ··· 1367 1364 * first *unfilled* event in the ring (following the last filled one). 1368 1365 * 1369 1366 * Events are sequential within the event ring, and transactions are 1370 - * sequential within the transaction pool. 1367 + * sequential within the transaction array. 1371 1368 * 1372 1369 * Note that @index always refers to an element *within* the event ring. 1373 1370 */
+5 -3
drivers/net/ipa/gsi.h
··· 83 83 struct gsi_trans_info { 84 84 atomic_t tre_avail; /* TREs available for allocation */ 85 85 struct gsi_trans_pool pool; /* transaction pool */ 86 + struct gsi_trans **map; /* TRE -> transaction map */ 87 + 86 88 struct gsi_trans_pool sg_pool; /* scatterlist pool */ 87 89 struct gsi_trans_pool cmd_pool; /* command payload DMA pool */ 88 - struct gsi_trans **map; /* TRE -> transaction map */ 89 90 90 91 spinlock_t spinlock; /* protects updates to the lists */ 91 92 struct list_head alloc; /* allocated, not committed */ 92 - struct list_head pending; /* committed, awaiting completion */ 93 + struct list_head committed; /* committed, awaiting doorbell */ 94 + struct list_head pending; /* pending, awaiting completion */ 93 95 struct list_head complete; /* completed, awaiting poll */ 94 96 struct list_head polled; /* returned by gsi_channel_poll_one() */ 95 97 }; ··· 187 185 * @gsi: GSI pointer 188 186 * @channel_id: Channel whose limit is to be returned 189 187 * 190 - * Return: The maximum number of TREs oustanding on the channel 188 + * Return: The maximum number of TREs outstanding on the channel 191 189 */ 192 190 u32 gsi_channel_tre_max(struct gsi *gsi, u32 channel_id); 193 191
+56 -35
drivers/net/ipa/gsi_trans.c
··· 241 241 struct gsi_trans, links); 242 242 } 243 243 244 - /* Move a transaction from the allocated list to the pending list */ 245 - static void gsi_trans_move_pending(struct gsi_trans *trans) 244 + /* Move a transaction from the allocated list to the committed list */ 245 + static void gsi_trans_move_committed(struct gsi_trans *trans) 246 246 { 247 247 struct gsi_channel *channel = &trans->gsi->channel[trans->channel_id]; 248 248 struct gsi_trans_info *trans_info = &channel->trans_info; 249 249 250 250 spin_lock_bh(&trans_info->spinlock); 251 251 252 - list_move_tail(&trans->links, &trans_info->pending); 252 + list_move_tail(&trans->links, &trans_info->committed); 253 + 254 + spin_unlock_bh(&trans_info->spinlock); 255 + } 256 + 257 + /* Move transactions from the committed list to the pending list */ 258 + static void gsi_trans_move_pending(struct gsi_trans *trans) 259 + { 260 + struct gsi_channel *channel = &trans->gsi->channel[trans->channel_id]; 261 + struct gsi_trans_info *trans_info = &channel->trans_info; 262 + struct list_head list; 263 + 264 + spin_lock_bh(&trans_info->spinlock); 265 + 266 + /* Move this transaction and all predecessors to the pending list */ 267 + list_cut_position(&list, &trans_info->committed, &trans->links); 268 + list_splice_tail(&list, &trans_info->pending); 253 269 254 270 spin_unlock_bh(&trans_info->spinlock); 255 271 } ··· 362 346 trans->rsvd_count = tre_count; 363 347 init_completion(&trans->completion); 364 348 365 - /* Allocate the scatterlist and (if requested) info entries. */ 349 + /* Allocate the scatterlist */ 366 350 trans->sgl = gsi_trans_pool_alloc(&trans_info->sg_pool, tre_count); 367 351 sg_init_marker(trans->sgl, tre_count); 368 352 ··· 404 388 if (!last) 405 389 return; 406 390 407 - ipa_gsi_trans_release(trans); 391 + if (trans->used_count) 392 + ipa_gsi_trans_release(trans); 408 393 409 394 /* Releasing the reserved TREs implicitly frees the sgl[] and 410 395 * (if present) info[] arrays, plus the transaction itself. ··· 598 581 if (channel->toward_ipa) 599 582 gsi_trans_tx_committed(trans); 600 583 601 - gsi_trans_move_pending(trans); 584 + gsi_trans_move_committed(trans); 602 585 603 586 /* Ring doorbell if requested, or if all TREs are allocated */ 604 587 if (ring_db || !atomic_read(&channel->trans_info.tre_avail)) { 605 588 /* Report what we're handing off to hardware for TX channels */ 606 589 if (channel->toward_ipa) 607 590 gsi_trans_tx_queued(trans); 591 + gsi_trans_move_pending(trans); 608 592 gsi_channel_doorbell(channel); 609 593 } 610 594 } ··· 710 692 int gsi_channel_trans_init(struct gsi *gsi, u32 channel_id) 711 693 { 712 694 struct gsi_channel *channel = &gsi->channel[channel_id]; 695 + u32 tre_count = channel->tre_count; 713 696 struct gsi_trans_info *trans_info; 714 697 u32 tre_max; 715 698 int ret; ··· 718 699 /* Ensure the size of a channel element is what's expected */ 719 700 BUILD_BUG_ON(sizeof(struct gsi_tre) != GSI_RING_ELEMENT_SIZE); 720 701 721 - /* The map array is used to determine what transaction is associated 722 - * with a TRE that the hardware reports has completed. We need one 723 - * map entry per TRE. 724 - */ 725 702 trans_info = &channel->trans_info; 726 - trans_info->map = kcalloc(channel->tre_count, sizeof(*trans_info->map), 727 - GFP_KERNEL); 728 - if (!trans_info->map) 729 - return -ENOMEM; 730 703 731 - /* We can't use more TREs than there are available in the ring. 732 - * This limits the number of transactions that can be oustanding. 733 - * Worst case is one TRE per transaction (but we actually limit 734 - * it to something a little less than that). We allocate resources 735 - * for transactions (including transaction structures) based on 736 - * this maximum number. 704 + /* The tre_avail field is what ultimately limits the number of 705 + * outstanding transactions and their resources. A transaction 706 + * allocation succeeds only if the TREs available are sufficient 707 + * for what the transaction might need. 737 708 */ 738 709 tre_max = gsi_channel_tre_max(channel->gsi, channel_id); 710 + atomic_set(&trans_info->tre_avail, tre_max); 739 711 740 - /* Transactions are allocated one at a time. */ 712 + /* We can't use more TREs than the number available in the ring. 713 + * This limits the number of transactions that can be outstanding. 714 + * Worst case is one TRE per transaction (but we actually limit 715 + * it to something a little less than that). By allocating a 716 + * power-of-two number of transactions we can use an index 717 + * modulo that number to determine the next one that's free. 718 + * Transactions are allocated one at a time. 719 + */ 741 720 ret = gsi_trans_pool_init(&trans_info->pool, sizeof(struct gsi_trans), 742 721 tre_max, 1); 743 722 if (ret) 744 - goto err_kfree; 723 + return -ENOMEM; 724 + 725 + /* A completion event contains a pointer to the TRE that caused 726 + * the event (which will be the last one used by the transaction). 727 + * Each entry in this map records the transaction associated 728 + * with a corresponding completed TRE. 729 + */ 730 + trans_info->map = kcalloc(tre_count, sizeof(*trans_info->map), 731 + GFP_KERNEL); 732 + if (!trans_info->map) { 733 + ret = -ENOMEM; 734 + goto err_trans_free; 735 + } 745 736 746 737 /* A transaction uses a scatterlist array to represent the data 747 738 * transfers implemented by the transaction. Each scatterlist ··· 763 734 sizeof(struct scatterlist), 764 735 tre_max, channel->trans_tre_max); 765 736 if (ret) 766 - goto err_trans_pool_exit; 767 - 768 - /* Finally, the tre_avail field is what ultimately limits the number 769 - * of outstanding transactions and their resources. A transaction 770 - * allocation succeeds only if the TREs available are sufficient for 771 - * what the transaction might need. Transaction resource pools are 772 - * sized based on the maximum number of outstanding TREs, so there 773 - * will always be resources available if there are TREs available. 774 - */ 775 - atomic_set(&trans_info->tre_avail, tre_max); 737 + goto err_map_free; 776 738 777 739 spin_lock_init(&trans_info->spinlock); 778 740 INIT_LIST_HEAD(&trans_info->alloc); 741 + INIT_LIST_HEAD(&trans_info->committed); 779 742 INIT_LIST_HEAD(&trans_info->pending); 780 743 INIT_LIST_HEAD(&trans_info->complete); 781 744 INIT_LIST_HEAD(&trans_info->polled); 782 745 783 746 return 0; 784 747 785 - err_trans_pool_exit: 786 - gsi_trans_pool_exit(&trans_info->pool); 787 - err_kfree: 748 + err_map_free: 788 749 kfree(trans_info->map); 750 + err_trans_free: 751 + gsi_trans_pool_exit(&trans_info->pool); 789 752 790 753 dev_err(gsi->dev, "error %d initializing channel %u transactions\n", 791 754 ret, channel_id);
+2
drivers/net/ipa/ipa_main.c
··· 836 836 kfree(ipa); 837 837 ipa_power_exit(power); 838 838 839 + dev_info(dev, "IPA driver removed"); 840 + 839 841 return 0; 840 842 } 841 843